From 1ca0223c7136b83e6f81a9ab9202e6917a1a506e Mon Sep 17 00:00:00 2001
From: mrowswares <83023433+mrowswares@users.noreply.github.com>
Date: Sun, 29 Aug 2021 17:19:26 +0100
Subject: [PATCH 01/56] remove straintime & speed skill caps, implement basic
doubletap cheese detection
---
.../Difficulty/OsuDifficultyCalculator.cs | 2 +-
.../Preprocessing/OsuDifficultyHitObject.cs | 2 +-
.../Difficulty/Skills/Speed.cs | 20 ++++++++++++++++---
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index e47f82fb39..cfd74a4174 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[]
{
new Aim(mods),
- new Speed(mods)
+ new Speed(mods, beatmap, clockRate)
};
protected override Mod[] DifficultyAdjustmentMods => new Mod[]
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
index fa6c5c4d9c..bc97172dbf 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
@@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
setDistances();
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
- StrainTime = Math.Max(50, DeltaTime);
+ StrainTime = DeltaTime;
}
private void setDistances()
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index f0eb199e5f..7bc16485eb 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
@@ -26,12 +27,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
protected override double DifficultyMultiplier => 1.04;
private const double min_speed_bonus = 75; // ~200BPM
- private const double max_speed_bonus = 45; // ~330BPM
private const double speed_balancing_factor = 40;
+ private double greatWindow;
- public Speed(Mod[] mods)
+ public Speed(Mod[] mods, IBeatmap beatmap, double clockRate)
: base(mods)
{
+ greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
+ Console.WriteLine(greatWindow);
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -42,12 +45,23 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var osuCurrent = (OsuDifficultyHitObject)current;
double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance);
- double deltaTime = Math.Max(max_speed_bonus, current.DeltaTime);
+ double deltaTime = current.DeltaTime;
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2);
+ // Doubletap detection
+ if (Previous.Count > 0)
+ {
+ var osuPrevious = (OsuDifficultyHitObject)Previous[0];
+ if ( (osuPrevious.DeltaTime / osuCurrent.DeltaTime) >= 3 && osuCurrent.DeltaTime <= (2 * greatWindow))
+ {
+ //Console.WriteLine( osuCurrent.StartTime / 1000.0);
+ return 0;
+ }
+ }
+
double angleBonus = 1.0;
if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin)
From a190038c33fec8b62784d4c64ae72aef28e15477 Mon Sep 17 00:00:00 2001
From: mrowswares <83023433+mrowswares@users.noreply.github.com>
Date: Sun, 29 Aug 2021 20:16:13 +0100
Subject: [PATCH 02/56] remove writelines
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 7bc16485eb..7cc5447888 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -34,7 +34,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
: base(mods)
{
greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
- Console.WriteLine(greatWindow);
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -57,7 +56,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var osuPrevious = (OsuDifficultyHitObject)Previous[0];
if ( (osuPrevious.DeltaTime / osuCurrent.DeltaTime) >= 3 && osuCurrent.DeltaTime <= (2 * greatWindow))
{
- //Console.WriteLine( osuCurrent.StartTime / 1000.0);
return 0;
}
}
From 711baa12bafc7bfa3186b545b421ee760dbcc653 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 2 Sep 2021 16:31:31 +0100
Subject: [PATCH 03/56] emu's doubletap cheese nerf
---
.../Difficulty/Skills/Speed.cs | 20 ++++++++-----------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 7cc5447888..8beef524de 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public Speed(Mod[] mods, IBeatmap beatmap, double clockRate)
: base(mods)
{
- greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
+ //greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -46,20 +46,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance);
double deltaTime = current.DeltaTime;
+ // Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
+ if (Previous.Count > 0)
+ {
+ deltaTime = Math.Max(Previous[0].DeltaTime, deltaTime);
+ }
+
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2);
- // Doubletap detection
- if (Previous.Count > 0)
- {
- var osuPrevious = (OsuDifficultyHitObject)Previous[0];
- if ( (osuPrevious.DeltaTime / osuCurrent.DeltaTime) >= 3 && osuCurrent.DeltaTime <= (2 * greatWindow))
- {
- return 0;
- }
- }
-
double angleBonus = 1.0;
if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin)
@@ -76,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
}
- return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime;
+ return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / deltaTime;
}
}
}
From 3e98c71ece670f63e7522a6deaf5740681d548d5 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 2 Sep 2021 16:48:34 +0100
Subject: [PATCH 04/56] cap deltatime to hitwindow sorta
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 8beef524de..3ce0d050d7 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public Speed(Mod[] mods, IBeatmap beatmap, double clockRate)
: base(mods)
{
- //greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
+ greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -52,6 +52,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
deltaTime = Math.Max(Previous[0].DeltaTime, deltaTime);
}
+ // Cap deltatime to the OD 300 hitwindow.
+ // 0.77 is derived from making sure 260bpm OD8 streams aren't nerfed
+ var hitWindowNerfRaw = deltaTime / (greatWindow * 2 * 0.77);
+ var hitWindowNerf = Math.Clamp(hitWindowNerfRaw, 0.85, 1);
+
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2);
@@ -72,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
}
- return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / deltaTime;
+ return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / (deltaTime / hitWindowNerf);
}
}
}
From d9cc497801fb37f45644f058805a05f51626a59b Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 2 Sep 2021 17:02:23 +0100
Subject: [PATCH 05/56] refactoring
---
.../Difficulty/OsuDifficultyCalculator.cs | 2 +-
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index cfd74a4174..74ede287b0 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[]
{
new Aim(mods),
- new Speed(mods, beatmap, clockRate)
+ new Speed(mods, beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, clockRate),
};
protected override Mod[] DifficultyAdjustmentMods => new Mod[]
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 3ce0d050d7..76803cbdf8 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -30,10 +30,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private const double speed_balancing_factor = 40;
private double greatWindow;
- public Speed(Mod[] mods, IBeatmap beatmap, double clockRate)
+ public Speed(Mod[] mods, float od, double clockRate)
: base(mods)
{
- greatWindow = (79 - (beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty * 6) + 0.5) / clockRate;
+ greatWindow = (79 - (od * 6) + 0.5) / clockRate;
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -54,8 +54,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
// Cap deltatime to the OD 300 hitwindow.
// 0.77 is derived from making sure 260bpm OD8 streams aren't nerfed
- var hitWindowNerfRaw = deltaTime / (greatWindow * 2 * 0.77);
- var hitWindowNerf = Math.Clamp(hitWindowNerfRaw, 0.85, 1);
+ var hitWindowNerf = deltaTime / (greatWindow * 2 * 0.77);
+ deltaTime /= Math.Clamp(hitWindowNerf, 0.92, 1);
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
@@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
}
- return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / (deltaTime / hitWindowNerf);
+ return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / deltaTime;
}
}
}
From 0d60076f3411d03937f9a1b3bcaa170f5ae30730 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 2 Sep 2021 17:14:23 +0100
Subject: [PATCH 06/56] fix doubletap cheese detect (base on hitwindow)
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 76803cbdf8..6cd32c798d 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double deltaTime = current.DeltaTime;
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- if (Previous.Count > 0)
+ if (Previous.Count > 0 && deltaTime <= greatWindow * 2)
{
deltaTime = Math.Max(Previous[0].DeltaTime, deltaTime);
}
From 57a2ba9aa80e5432cfe0fcaa31618f85bf97e4ad Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 2 Sep 2021 18:29:55 +0100
Subject: [PATCH 07/56] remove "straintime"
---
.../Difficulty/Preprocessing/OsuDifficultyHitObject.cs | 8 --------
osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 6 +++---
2 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
index bc97172dbf..609ad4c995 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
@@ -32,11 +32,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
///
public double? Angle { get; private set; }
- ///
- /// Milliseconds elapsed since the start time of the previous , with a minimum of 50ms.
- ///
- public readonly double StrainTime;
-
private readonly OsuHitObject lastLastObject;
private readonly OsuHitObject lastObject;
@@ -47,9 +42,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
this.lastObject = (OsuHitObject)lastObject;
setDistances();
-
- // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
- StrainTime = DeltaTime;
}
private void setDistances()
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
index 16a18cbcb9..63daea1ade 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
@@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
Math.Max(osuPrevious.JumpDistance - scale, 0)
* Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2)
* Math.Max(osuCurrent.JumpDistance - scale, 0));
- result = 1.4 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.StrainTime);
+ result = 1.4 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.DeltaTime);
}
}
@@ -54,8 +54,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double travelDistanceExp = applyDiminishingExp(osuCurrent.TravelDistance);
return Math.Max(
- result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.StrainTime, timing_threshold),
- (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.StrainTime
+ result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.DeltaTime, timing_threshold),
+ (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.DeltaTime
);
}
From 0beef9c1e7ed296401b347a42811029b593379f0 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Fri, 3 Sep 2021 02:20:22 +0100
Subject: [PATCH 08/56] made double cheese detection stricter
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 6cd32c798d..c4230fc9a4 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double deltaTime = current.DeltaTime;
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- if (Previous.Count > 0 && deltaTime <= greatWindow * 2)
+ if (Previous.Count > 0 && deltaTime <= greatWindow)
{
deltaTime = Math.Max(Previous[0].DeltaTime, deltaTime);
}
From bf87a4b2d3802cfdd17b04f412fc9c9f9ab98799 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Fri, 3 Sep 2021 02:39:21 +0100
Subject: [PATCH 09/56] interpolate the doubletap cheese nerf instead
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index c4230fc9a4..836e926cf1 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -2,11 +2,11 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Objects;
+using osu.Framework.Utils;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
@@ -47,9 +47,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double deltaTime = current.DeltaTime;
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- if (Previous.Count > 0 && deltaTime <= greatWindow)
+ double deltaTimeThreshold = greatWindow * 2;
+
+ if (Previous.Count > 0 && deltaTime < deltaTimeThreshold && Previous[0].DeltaTime > deltaTime)
{
- deltaTime = Math.Max(Previous[0].DeltaTime, deltaTime);
+ double closenessToZero = Math.Min(1, deltaTime / deltaTimeThreshold);
+ deltaTime = Interpolation.Lerp(Previous[0].DeltaTime, deltaTime, closenessToZero);
}
// Cap deltatime to the OD 300 hitwindow.
From 8654a0af05798ec1a8db0c8af9e9e737b523c724 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Fri, 3 Sep 2021 03:01:25 +0100
Subject: [PATCH 10/56] remove unnecessary min & renamed variable so its more
descriptive
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 836e926cf1..fb24476493 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
if (Previous.Count > 0 && deltaTime < deltaTimeThreshold && Previous[0].DeltaTime > deltaTime)
{
- double closenessToZero = Math.Min(1, deltaTime / deltaTimeThreshold);
- deltaTime = Interpolation.Lerp(Previous[0].DeltaTime, deltaTime, closenessToZero);
+ double speedWindowRatio = deltaTime / deltaTimeThreshold;
+ deltaTime = Interpolation.Lerp(Previous[0].DeltaTime, deltaTime, speedWindowRatio);
}
// Cap deltatime to the OD 300 hitwindow.
From 3fce3f620f5903f2aee9ee7566273a887d48be62 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Sat, 4 Sep 2021 16:56:15 +0100
Subject: [PATCH 11/56] use OsuHitWindows, amend comment
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index fb24476493..e69f15188d 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -7,6 +7,8 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Objects;
using osu.Framework.Utils;
+using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.Osu.Scoring;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
@@ -33,7 +35,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public Speed(Mod[] mods, float od, double clockRate)
: base(mods)
{
- greatWindow = (79 - (od * 6) + 0.5) / clockRate;
+ HitWindows hitWindows = new OsuHitWindows();
+ hitWindows.SetDifficulty(od);
+ greatWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
}
protected override double StrainValueOf(DifficultyHitObject current)
@@ -56,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
// Cap deltatime to the OD 300 hitwindow.
- // 0.77 is derived from making sure 260bpm OD8 streams aren't nerfed
+ // 0.77 is derived from making sure 260bpm OD8 streams aren't nerfed harshly
var hitWindowNerf = deltaTime / (greatWindow * 2 * 0.77);
deltaTime /= Math.Clamp(hitWindowNerf, 0.92, 1);
From e9f7258f2b3110d4845699602e6dbdab49713895 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Mon, 13 Sep 2021 14:50:40 +0100
Subject: [PATCH 12/56] adjust hitwindow nerf to be harsher
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index e69f15188d..2640d4ac41 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -60,8 +60,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
// Cap deltatime to the OD 300 hitwindow.
- // 0.77 is derived from making sure 260bpm OD8 streams aren't nerfed harshly
- var hitWindowNerf = deltaTime / (greatWindow * 2 * 0.77);
+ // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly
+ var hitWindowNerf = deltaTime / (greatWindow * 2 * 0.93);
deltaTime /= Math.Clamp(hitWindowNerf, 0.92, 1);
double speedBonus = 1.0;
From 8796e45f63447ec2de4c89f4d03af0b384ec264a Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 14 Sep 2021 15:22:03 +0100
Subject: [PATCH 13/56] prevent 2B objects from dividing by zero
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 2 +-
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
index 63daea1ade..7467feb009 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
@@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return Math.Max(
result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.DeltaTime, timing_threshold),
- (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.DeltaTime
+ (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / Math.Max(osuCurrent.DeltaTime, 1)
);
}
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 2640d4ac41..39acbf4027 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
}
- return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / deltaTime;
+ return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / Math.Max(deltaTime, 1);
}
}
}
From 6d254fba0ac2001d559f5debb8ca1c953d60c23e Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 10:27:18 +0100
Subject: [PATCH 14/56] digestify speed return
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 39acbf4027..19f9e3f849 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -84,7 +84,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
}
- return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / Math.Max(deltaTime, 1);
+ return (1 + (speedBonus - 1) * 0.75)
+ * angleBonus
+ * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5))
+ / Math.Max(deltaTime, 1);
}
}
}
From 49658b6f82d097777705f6eaa670bd0fc4339be6 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 10:29:30 +0100
Subject: [PATCH 15/56] set greatWindow to readonly
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 19f9e3f849..93d3227649 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -30,7 +30,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private const double min_speed_bonus = 75; // ~200BPM
private const double speed_balancing_factor = 40;
- private double greatWindow;
+
+ private readonly double greatWindow;
public Speed(Mod[] mods, float od, double clockRate)
: base(mods)
From a0bd73c3562211320410bbd63d157af0143ba377 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 10:52:50 +0100
Subject: [PATCH 16/56] refactor hit window calc
---
.../Difficulty/OsuDifficultyCalculator.cs | 24 ++++++++++++-------
.../Difficulty/Skills/Speed.cs | 6 ++---
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 74ede287b0..9107d8234f 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing;
@@ -21,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
public class OsuDifficultyCalculator : DifficultyCalculator
{
private const double difficulty_multiplier = 0.0675;
+ private double hitWindowGreat;
public OsuDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap)
@@ -36,11 +38,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2;
- HitWindows hitWindows = new OsuHitWindows();
- hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
-
- // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future
- double hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
int maxCombo = beatmap.HitObjects.Count;
@@ -79,11 +76,20 @@ namespace osu.Game.Rulesets.Osu.Difficulty
}
}
- protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[]
+ protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
{
- new Aim(mods),
- new Speed(mods, beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, clockRate),
- };
+ HitWindows hitWindows = new OsuHitWindows();
+ hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
+
+ // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future
+ hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
+
+ return new Skill[]
+ {
+ new Aim(mods),
+ new Speed(mods, hitWindowGreat),
+ };
+ }
protected override Mod[] DifficultyAdjustmentMods => new Mod[]
{
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 93d3227649..8f0034ef79 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -33,12 +33,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private readonly double greatWindow;
- public Speed(Mod[] mods, float od, double clockRate)
+ public Speed(Mod[] mods, double hitWindowGreat)
: base(mods)
{
- HitWindows hitWindows = new OsuHitWindows();
- hitWindows.SetDifficulty(od);
- greatWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
+ greatWindow = hitWindowGreat;
}
protected override double StrainValueOf(DifficultyHitObject current)
From 3a16ec277a8fdac95f890599d4d7db56491fae70 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 11:12:36 +0100
Subject: [PATCH 17/56] refactor speed window ratios
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 8f0034ef79..89e5c39449 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -49,19 +49,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance);
double deltaTime = current.DeltaTime;
- // Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- double deltaTimeThreshold = greatWindow * 2;
+ double greatWindowFull = greatWindow * 2;
+ double speedWindowRatio = deltaTime / greatWindowFull;
- if (Previous.Count > 0 && deltaTime < deltaTimeThreshold && Previous[0].DeltaTime > deltaTime)
+ // Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
+ if (Previous.Count > 0 && deltaTime < greatWindowFull && Previous[0].DeltaTime > deltaTime)
{
- double speedWindowRatio = deltaTime / deltaTimeThreshold;
+
deltaTime = Interpolation.Lerp(Previous[0].DeltaTime, deltaTime, speedWindowRatio);
}
// Cap deltatime to the OD 300 hitwindow.
- // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly
- var hitWindowNerf = deltaTime / (greatWindow * 2 * 0.93);
- deltaTime /= Math.Clamp(hitWindowNerf, 0.92, 1);
+ // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly,
+ deltaTime /= Math.Clamp(speedWindowRatio * (1/0.93), 0.92, 1);
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
From 4017598af0420a71ab769b4dde2b24ecd5adf512 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 11:15:05 +0100
Subject: [PATCH 18/56] simplify algebra down
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 89e5c39449..aefebbe669 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
// Cap deltatime to the OD 300 hitwindow.
// 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly,
- deltaTime /= Math.Clamp(speedWindowRatio * (1/0.93), 0.92, 1);
+ deltaTime /= Math.Clamp(speedWindowRatio / 0.93, 0.92, 1);
double speedBonus = 1.0;
if (deltaTime < min_speed_bonus)
From 7f6722e43fcd4aa19a5e3d65a189959714d64d5c Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 11:24:48 +0100
Subject: [PATCH 19/56] throw math.max(N, 1) into straintime
---
.../Preprocessing/OsuDifficultyHitObject.cs | 8 ++++++++
osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 6 +++---
.../Difficulty/Skills/Speed.cs | 17 ++++++++---------
3 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
index 609ad4c995..65efe65129 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
@@ -16,6 +16,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
protected new OsuHitObject BaseObject => (OsuHitObject)base.BaseObject;
+ ///
+ /// Milliseconds elapsed since the start time of the previous , with a minimum of 1ms to account for simultaneous s.
+ ///
+ public double StrainTime { get; private set; }
+
///
/// Normalized distance from the end position of the previous to the start position of this .
///
@@ -42,6 +47,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
this.lastObject = (OsuHitObject)lastObject;
setDistances();
+
+ // Capped to 1ms to prevent difficulty calculation breaking from simulatenous objects.
+ StrainTime = Math.Max(DeltaTime, 1);
}
private void setDistances()
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
index 7467feb009..16a18cbcb9 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
@@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
Math.Max(osuPrevious.JumpDistance - scale, 0)
* Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2)
* Math.Max(osuCurrent.JumpDistance - scale, 0));
- result = 1.4 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.DeltaTime);
+ result = 1.4 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.StrainTime);
}
}
@@ -54,8 +54,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double travelDistanceExp = applyDiminishingExp(osuCurrent.TravelDistance);
return Math.Max(
- result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.DeltaTime, timing_threshold),
- (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / Math.Max(osuCurrent.DeltaTime, 1)
+ result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.StrainTime, timing_threshold),
+ (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.StrainTime
);
}
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index aefebbe669..b2eacc5c6a 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -47,25 +47,24 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var osuCurrent = (OsuDifficultyHitObject)current;
double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance);
- double deltaTime = current.DeltaTime;
+ double strainTime = osuCurrent.StrainTime;
double greatWindowFull = greatWindow * 2;
- double speedWindowRatio = deltaTime / greatWindowFull;
+ double speedWindowRatio = strainTime / greatWindowFull;
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- if (Previous.Count > 0 && deltaTime < greatWindowFull && Previous[0].DeltaTime > deltaTime)
+ if (Previous.Count > 0 && strainTime < greatWindowFull && (Previous[0] as OsuDifficultyHitObject).StrainTime > strainTime)
{
-
- deltaTime = Interpolation.Lerp(Previous[0].DeltaTime, deltaTime, speedWindowRatio);
+ strainTime = Interpolation.Lerp(Previous[0].DeltaTime, strainTime, speedWindowRatio);
}
// Cap deltatime to the OD 300 hitwindow.
// 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly,
- deltaTime /= Math.Clamp(speedWindowRatio / 0.93, 0.92, 1);
+ strainTime /= Math.Clamp(speedWindowRatio / 0.93, 0.92, 1);
double speedBonus = 1.0;
- if (deltaTime < min_speed_bonus)
- speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2);
+ if (strainTime < min_speed_bonus)
+ speedBonus = 1 + Math.Pow((min_speed_bonus - strainTime) / speed_balancing_factor, 2);
double angleBonus = 1.0;
@@ -86,7 +85,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return (1 + (speedBonus - 1) * 0.75)
* angleBonus
* (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5))
- / Math.Max(deltaTime, 1);
+ / strainTime;
}
}
}
From 2fe0681310498718bea523b550109743c511a0d9 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 12:03:47 +0100
Subject: [PATCH 20/56] elaborate comment
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index b2eacc5c6a..5b509b9edc 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
// Cap deltatime to the OD 300 hitwindow.
- // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly,
+ // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap.
strainTime /= Math.Clamp(speedWindowRatio / 0.93, 0.92, 1);
double speedBonus = 1.0;
From cf63a45f32dd10d7be11d959f8667a8b2ba544e4 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 12:36:15 +0100
Subject: [PATCH 21/56] swap speedwindowratio in cap so values are correct
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 5b509b9edc..78c3db96a1 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
// Cap deltatime to the OD 300 hitwindow.
// 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap.
- strainTime /= Math.Clamp(speedWindowRatio / 0.93, 0.92, 1);
+ strainTime /= Math.Clamp((strainTime / greatWindowFull) / 0.93, 0.92, 1);
double speedBonus = 1.0;
if (strainTime < min_speed_bonus)
From 463b92fcca42f0aa0e14307f21a7d60e46c7e080 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 12:41:29 +0100
Subject: [PATCH 22/56] remove unused strings
---
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 1 -
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 --
2 files changed, 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 9107d8234f..743494abac 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 78c3db96a1..a117570e61 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -7,8 +7,6 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Objects;
using osu.Framework.Utils;
-using osu.Game.Rulesets.Scoring;
-using osu.Game.Rulesets.Osu.Scoring;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
From 2c3e7bfd2dceddb7d8400c40a3ec5bcad2c436c7 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 15:27:36 +0100
Subject: [PATCH 23/56] moved 2b straintime cap up to 25ms
---
.../Difficulty/Preprocessing/OsuDifficultyHitObject.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
index 65efe65129..8e8f9bc06e 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
protected new OsuHitObject BaseObject => (OsuHitObject)base.BaseObject;
///
- /// Milliseconds elapsed since the start time of the previous , with a minimum of 1ms to account for simultaneous s.
+ /// Milliseconds elapsed since the start time of the previous , with a minimum of 25ms to account for simultaneous s.
///
public double StrainTime { get; private set; }
@@ -48,8 +48,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
setDistances();
- // Capped to 1ms to prevent difficulty calculation breaking from simulatenous objects.
- StrainTime = Math.Max(DeltaTime, 1);
+ // Capped to 25ms to prevent difficulty calculation breaking from simulatenous objects.
+ StrainTime = Math.Max(DeltaTime, 25);
}
private void setDistances()
From 2637c063a951b675edf4abd3d815e9c9ae33ebf9 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 15 Sep 2021 15:40:26 +0100
Subject: [PATCH 24/56] forgot a deltatime
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index a117570e61..3cb0e3506b 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
if (Previous.Count > 0 && strainTime < greatWindowFull && (Previous[0] as OsuDifficultyHitObject).StrainTime > strainTime)
{
- strainTime = Interpolation.Lerp(Previous[0].DeltaTime, strainTime, speedWindowRatio);
+ strainTime = Interpolation.Lerp((Previous[0] as OsuDifficultyHitObject).StrainTime, strainTime, speedWindowRatio);
}
// Cap deltatime to the OD 300 hitwindow.
From 7976442aec419492c30fa0b121c3ce9e00c33a9a Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Thu, 16 Sep 2021 14:20:42 +0900
Subject: [PATCH 25/56] Fix CI issues
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 3cb0e3506b..9364b11048 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -43,6 +43,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return 0;
var osuCurrent = (OsuDifficultyHitObject)current;
+ var osuPrevious = Previous.Count > 0 ? (OsuDifficultyHitObject)Previous[0] : null;
double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance);
double strainTime = osuCurrent.StrainTime;
@@ -51,10 +52,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double speedWindowRatio = strainTime / greatWindowFull;
// Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between)
- if (Previous.Count > 0 && strainTime < greatWindowFull && (Previous[0] as OsuDifficultyHitObject).StrainTime > strainTime)
- {
- strainTime = Interpolation.Lerp((Previous[0] as OsuDifficultyHitObject).StrainTime, strainTime, speedWindowRatio);
- }
+ if (osuPrevious != null && strainTime < greatWindowFull && osuPrevious.StrainTime > strainTime)
+ strainTime = Interpolation.Lerp(osuPrevious.StrainTime, strainTime, speedWindowRatio);
// Cap deltatime to the OD 300 hitwindow.
// 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap.
@@ -81,9 +80,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
return (1 + (speedBonus - 1) * 0.75)
- * angleBonus
- * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5))
- / strainTime;
+ * angleBonus
+ * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5))
+ / strainTime;
}
}
}
From c9e76783e64630cd1b9d9b08bebe108d41511886 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Fri, 17 Sep 2021 17:14:56 +0900
Subject: [PATCH 26/56] Fix taiko HD not calculating pre-empt correctly
---
.../Mods/TaikoModHidden.cs | 29 +++++++------------
.../UI/DrawableTaikoRuleset.cs | 10 +++++++
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index a6b3fe1cd9..5104fd9cff 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -2,43 +2,41 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
-using osu.Game.Beatmaps;
-using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
+using osu.Game.Rulesets.Taiko.UI;
+using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Taiko.Mods
{
- public class TaikoModHidden : ModHidden
+ public class TaikoModHidden : ModHidden, IApplicableToDrawableRuleset
{
public override string Description => @"Beats fade out before you hit them!";
public override double ScoreMultiplier => 1.06;
- private ControlPointInfo controlPointInfo;
+ private DrawableTaikoRuleset drawableRuleset;
+
+ public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset)
+ {
+ this.drawableRuleset = (DrawableTaikoRuleset)drawableRuleset;
+ }
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
ApplyNormalVisibilityState(hitObject, state);
}
- protected double MultiplierAt(double position)
- {
- double beatLength = controlPointInfo.TimingPointAt(position).BeatLength;
- double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier;
-
- return speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength;
- }
-
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
switch (hitObject)
{
case DrawableDrumRollTick _:
case DrawableHit _:
- double preempt = 10000 / MultiplierAt(hitObject.HitObject.StartTime);
+ double preempt = drawableRuleset.TimeRange.Value / drawableRuleset.ControlPointAt(hitObject.HitObject.StartTime).Multiplier;
double start = hitObject.HitObject.StartTime - preempt * 0.6;
double duration = preempt * 0.3;
@@ -56,10 +54,5 @@ namespace osu.Game.Rulesets.Taiko.Mods
break;
}
}
-
- public override void ApplyToBeatmap(IBeatmap beatmap)
- {
- controlPointInfo = beatmap.ControlPointInfo;
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs
index 6ddbf3c16b..824b95639b 100644
--- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs
+++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -16,6 +17,7 @@ using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Timing;
using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Scoring;
using osu.Game.Skinning;
@@ -60,6 +62,14 @@ namespace osu.Game.Rulesets.Taiko.UI
scroller.Height = ToLocalSpace(playfieldScreen.TopLeft + new Vector2(0, playfieldScreen.Height / 20)).Y;
}
+ public MultiplierControlPoint ControlPointAt(double time)
+ {
+ int result = ControlPoints.BinarySearch(new MultiplierControlPoint(time));
+ if (result < 0)
+ result = Math.Clamp(~result - 1, 0, ControlPoints.Count);
+ return ControlPoints[result];
+ }
+
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer();
protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo);
From ea68be08cb3fa6badd2f5df51f3fc5bc8a1901e8 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Fri, 17 Sep 2021 17:27:54 +0900
Subject: [PATCH 27/56] Split magic values into named constants
---
osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index 5104fd9cff..b3a54521d8 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -18,6 +18,18 @@ namespace osu.Game.Rulesets.Taiko.Mods
public override string Description => @"Beats fade out before you hit them!";
public override double ScoreMultiplier => 1.06;
+ ///
+ /// How far away from the hit target should hitobjects start to fade out.
+ /// Range: [0, 1]
+ ///
+ private const float fade_out_start_time = 0.6f;
+
+ ///
+ /// How long hitobjects take to fade out, in terms of the scrolling length.
+ /// Range: [0, 1]
+ ///
+ private const float fade_out_duration = 0.3f;
+
private DrawableTaikoRuleset drawableRuleset;
public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset)
@@ -37,8 +49,8 @@ namespace osu.Game.Rulesets.Taiko.Mods
case DrawableDrumRollTick _:
case DrawableHit _:
double preempt = drawableRuleset.TimeRange.Value / drawableRuleset.ControlPointAt(hitObject.HitObject.StartTime).Multiplier;
- double start = hitObject.HitObject.StartTime - preempt * 0.6;
- double duration = preempt * 0.3;
+ double start = hitObject.HitObject.StartTime - preempt * fade_out_start_time;
+ double duration = preempt * fade_out_duration;
using (hitObject.BeginAbsoluteSequence(start))
{
From 5dd0e0d961dacbd71a27d0e340c71a62a7bd3e35 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Fri, 17 Sep 2021 17:33:32 +0900
Subject: [PATCH 28/56] Don't apply normal visibility to increased visibility
state
---
osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index b3a54521d8..baad65297c 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -39,7 +39,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
- ApplyNormalVisibilityState(hitObject, state);
}
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
From a4238e49a70b30a6f3a97f61c7731b29d91b2afb Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Fri, 17 Sep 2021 17:39:34 +0900
Subject: [PATCH 29/56] Revert "Don't apply normal visibility to increased
visibility state"
This reverts commit 5dd0e0d961dacbd71a27d0e340c71a62a7bd3e35.
---
osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index baad65297c..b3a54521d8 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
+ ApplyNormalVisibilityState(hitObject, state);
}
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
From 56e80a07060e959948e109433f93aab43e501fa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Sep 2021 16:41:30 +0200
Subject: [PATCH 30/56] Add rectangular position snap grid
---
.../TestSceneRectangularPositionSnapGrid.cs | 103 ++++++++++++++++++
.../Components/RectangularPositionSnapGrid.cs | 101 +++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
create mode 100644 osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
new file mode 100644
index 0000000000..ec267bf752
--- /dev/null
+++ b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
@@ -0,0 +1,103 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input.Events;
+using osu.Game.Screens.Edit.Compose.Components;
+using osuTK;
+using osuTK.Graphics;
+
+namespace osu.Game.Tests.Visual.Editing
+{
+ public class TestSceneRectangularPositionSnapGrid : OsuManualInputManagerTestScene
+ {
+ private Container content;
+ protected override Container Content => content;
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ base.Content.AddRange(new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Colour4.Gray
+ },
+ content = new Container
+ {
+ RelativeSizeAxes = Axes.Both
+ }
+ });
+ }
+
+ private static readonly object[][] test_cases =
+ {
+ new object[] { new Vector2(0, 0), new Vector2(10, 10) },
+ new object[] { new Vector2(240, 180), new Vector2(10, 15) },
+ new object[] { new Vector2(160, 120), new Vector2(30, 20) },
+ new object[] { new Vector2(480, 360), new Vector2(100, 100) },
+ };
+
+ [TestCaseSource(nameof(test_cases))]
+ public void TestRectangularGrid(Vector2 position, Vector2 spacing)
+ {
+ RectangularPositionSnapGrid grid = null;
+
+ AddStep("create grid", () => Child = grid = new RectangularPositionSnapGrid(position, spacing)
+ {
+ RelativeSizeAxes = Axes.Both
+ });
+
+ AddStep("add snapping cursor", () => Add(new SnappingCursorContainer
+ {
+ RelativeSizeAxes = Axes.Both,
+ GetSnapPosition = pos => grid.GetSnappedPosition(grid.ToLocalSpace(pos))
+ }));
+ }
+
+ private class SnappingCursorContainer : CompositeDrawable
+ {
+ public Func GetSnapPosition;
+
+ private readonly Drawable cursor;
+
+ public SnappingCursorContainer()
+ {
+ RelativeSizeAxes = Axes.Both;
+
+ InternalChild = cursor = new Circle
+ {
+ Origin = Anchor.Centre,
+ Size = new Vector2(50),
+ Colour = Color4.Red
+ };
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ updatePosition(GetContainingInputManager().CurrentState.Mouse.Position);
+ }
+
+ protected override bool OnMouseMove(MouseMoveEvent e)
+ {
+ base.OnMouseMove(e);
+
+ updatePosition(e.ScreenSpaceMousePosition);
+ return true;
+ }
+
+ private void updatePosition(Vector2 screenSpacePosition)
+ {
+ cursor.Position = GetSnapPosition.Invoke(screenSpacePosition);
+ }
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
new file mode 100644
index 0000000000..f243c027e3
--- /dev/null
+++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
@@ -0,0 +1,101 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Layout;
+using osuTK;
+
+namespace osu.Game.Screens.Edit.Compose.Components
+{
+ public class RectangularPositionSnapGrid : CompositeDrawable
+ {
+ ///
+ /// The position of the origin of this in local coordinates.
+ ///
+ public Vector2 StartPosition { get; }
+
+ ///
+ /// The spacing between grid lines of this .
+ ///
+ public Vector2 Spacing { get; }
+
+ private readonly LayoutValue gridCache = new LayoutValue(Invalidation.RequiredParentSizeToFit);
+
+ public RectangularPositionSnapGrid(Vector2 startPosition, Vector2 spacing)
+ {
+ StartPosition = startPosition;
+ Spacing = spacing;
+
+ AddLayout(gridCache);
+ }
+
+ protected override void Update()
+ {
+ base.Update();
+
+ if (!gridCache.IsValid)
+ {
+ ClearInternal();
+ createContent();
+ gridCache.Validate();
+ }
+ }
+
+ private void createContent()
+ {
+ var drawSize = DrawSize;
+
+ generateGridLines(Direction.Horizontal, StartPosition.Y, 0, -Spacing.Y);
+ generateGridLines(Direction.Horizontal, StartPosition.Y, drawSize.Y, Spacing.Y);
+
+ generateGridLines(Direction.Vertical, StartPosition.X, 0, -Spacing.X);
+ generateGridLines(Direction.Vertical, StartPosition.X, drawSize.X, Spacing.X);
+ }
+
+ private void generateGridLines(Direction direction, float startPosition, float endPosition, float step)
+ {
+ int index = 0;
+ float currentPosition = startPosition;
+
+ while ((endPosition - currentPosition) * Math.Sign(step) > 0)
+ {
+ var gridLine = new Box
+ {
+ Colour = Colour4.White,
+ Alpha = index == 0 ? 0.3f : 0.1f,
+ EdgeSmoothness = new Vector2(0.2f)
+ };
+
+ if (direction == Direction.Horizontal)
+ {
+ gridLine.RelativeSizeAxes = Axes.X;
+ gridLine.Height = 1;
+ gridLine.Y = currentPosition;
+ }
+ else
+ {
+ gridLine.RelativeSizeAxes = Axes.Y;
+ gridLine.Width = 1;
+ gridLine.X = currentPosition;
+ }
+
+ AddInternal(gridLine);
+
+ index += 1;
+ currentPosition = startPosition + index * step;
+ }
+ }
+
+ public Vector2 GetSnappedPosition(Vector2 original)
+ {
+ Vector2 relativeToStart = original - StartPosition;
+ Vector2 offset = Vector2.Divide(relativeToStart, Spacing);
+ Vector2 roundedOffset = new Vector2(MathF.Round(offset.X), MathF.Round(offset.Y));
+
+ return StartPosition + Vector2.Multiply(roundedOffset, Spacing);
+ }
+ }
+}
From e1738025d439733586b88ea2b08d12a976f6fbd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Sep 2021 17:48:29 +0200
Subject: [PATCH 31/56] Add basic integration of rectangular grid to osu!
composer
---
.../Edit/OsuHitObjectComposer.cs | 57 ++++++++++++++++---
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index 806b7e6051..491ad655fa 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -17,6 +17,7 @@ using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
+using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Components.TernaryButtons;
using osu.Game.Screens.Edit.Compose.Components;
@@ -42,10 +43,12 @@ namespace osu.Game.Rulesets.Osu.Edit
};
private readonly Bindable distanceSnapToggle = new Bindable();
+ private readonly Bindable gridSnapToggle = new Bindable();
protected override IEnumerable CreateTernaryButtons() => base.CreateTernaryButtons().Concat(new[]
{
- new TernaryButton(distanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Ruler })
+ new TernaryButton(distanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Ruler }),
+ new TernaryButton(gridSnapToggle, "Grid Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Th })
});
private BindableList selectedHitObjects;
@@ -63,6 +66,10 @@ namespace osu.Game.Rulesets.Osu.Edit
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners }
},
distanceSnapGridContainer = new Container
+ {
+ RelativeSizeAxes = Axes.Both
+ },
+ rectangularPositionSnapGridContainer = new Container
{
RelativeSizeAxes = Axes.Both
}
@@ -73,7 +80,21 @@ namespace osu.Game.Rulesets.Osu.Edit
placementObject = EditorBeatmap.PlacementObject.GetBoundCopy();
placementObject.ValueChanged += _ => updateDistanceSnapGrid();
- distanceSnapToggle.ValueChanged += _ => updateDistanceSnapGrid();
+ distanceSnapToggle.ValueChanged += _ =>
+ {
+ updateDistanceSnapGrid();
+
+ if (distanceSnapToggle.Value == TernaryState.True)
+ gridSnapToggle.Value = TernaryState.False;
+ };
+
+ gridSnapToggle.ValueChanged += _ =>
+ {
+ updateRectangularPositionSnapGrid();
+
+ if (gridSnapToggle.Value == TernaryState.True)
+ distanceSnapToggle.Value = TernaryState.False;
+ };
// we may be entering the screen with a selection already active
updateDistanceSnapGrid();
@@ -122,13 +143,19 @@ namespace osu.Game.Rulesets.Osu.Edit
if (positionSnap.ScreenSpacePosition != screenSpacePosition)
return positionSnap;
- // will be null if distance snap is disabled or not feasible for the current time value.
- if (distanceSnapGrid == null)
- return base.SnapScreenSpacePositionToValidTime(screenSpacePosition);
+ if (distanceSnapGrid != null)
+ {
+ (Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition));
+ return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time, PlayfieldAtScreenSpacePosition(screenSpacePosition));
+ }
- (Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition));
+ if (rectangularPositionSnapGrid != null)
+ {
+ Vector2 pos = rectangularPositionSnapGrid.GetSnappedPosition(rectangularPositionSnapGrid.ToLocalSpace(screenSpacePosition));
+ return new SnapResult(rectangularPositionSnapGrid.ToScreenSpace(pos), null, PlayfieldAtScreenSpacePosition(screenSpacePosition));
+ }
- return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time, PlayfieldAtScreenSpacePosition(screenSpacePosition));
+ return base.SnapScreenSpacePositionToValidTime(screenSpacePosition);
}
private bool snapToVisibleBlueprints(Vector2 screenSpacePosition, out SnapResult snapResult)
@@ -272,5 +299,21 @@ namespace osu.Game.Rulesets.Osu.Edit
return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject);
}
+
+ private Container rectangularPositionSnapGridContainer;
+ private RectangularPositionSnapGrid rectangularPositionSnapGrid;
+
+ private void updateRectangularPositionSnapGrid()
+ {
+ rectangularPositionSnapGridContainer.Clear();
+
+ if (gridSnapToggle.Value == TernaryState.True)
+ {
+ rectangularPositionSnapGridContainer.Add(rectangularPositionSnapGrid = new RectangularPositionSnapGrid(OsuPlayfield.BASE_SIZE / 2, new Vector2(16))
+ {
+ RelativeSizeAxes = Axes.Both
+ });
+ }
+ }
}
}
From c403e628ddae77c9c3173604e8c9832dd09b8a6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Sep 2021 17:58:32 +0200
Subject: [PATCH 32/56] Add test coverage for distance/rectangular grid
exclusivity
---
.../Editor/TestSceneOsuEditorGrids.cs | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
new file mode 100644
index 0000000000..007b27b2e7
--- /dev/null
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -0,0 +1,34 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using NUnit.Framework;
+using osu.Framework.Testing;
+using osu.Game.Rulesets.Osu.Edit;
+using osu.Game.Screens.Edit.Compose.Components;
+using osu.Game.Tests.Visual;
+using osuTK.Input;
+
+namespace osu.Game.Rulesets.Osu.Tests.Editor
+{
+ public class TestSceneOsuEditorGrids : EditorTestScene
+ {
+ protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
+
+ [Test]
+ public void TestGridExclusivity()
+ {
+ AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
+ AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
+ AddUntilStep("distance snap grid visible", () => this.ChildrenOfType().Any());
+
+ AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
+ AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType().Any());
+ AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
+
+ AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
+ AddUntilStep("distance snap grid visible", () => this.ChildrenOfType().Any());
+ AddUntilStep("rectangular grid hidden", () => !this.ChildrenOfType().Any());
+ }
+ }
+}
From 4e094b2127d614fc3d1943351bad9de1a239b83c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Sep 2021 18:45:22 +0200
Subject: [PATCH 33/56] Implement grid size toggling matching stable
---
.../Editor/TestSceneOsuEditorGrids.cs | 28 +++++++++--
.../Edit/OsuHitObjectComposer.cs | 3 +-
.../Edit/OsuRectangularPositionSnapGrid.cs | 50 +++++++++++++++++++
.../TestSceneRectangularPositionSnapGrid.cs | 5 +-
.../Components/RectangularPositionSnapGrid.cs | 18 +++++--
5 files changed, 94 insertions(+), 10 deletions(-)
create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
index 007b27b2e7..81e44a57db 100644
--- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -5,8 +5,8 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Rulesets.Osu.Edit;
-using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Tests.Visual;
+using osuTK;
using osuTK.Input;
namespace osu.Game.Rulesets.Osu.Tests.Editor
@@ -24,11 +24,33 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType().Any());
- AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
+ AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType().Any());
- AddUntilStep("rectangular grid hidden", () => !this.ChildrenOfType().Any());
+ AddUntilStep("rectangular grid hidden", () => !this.ChildrenOfType().Any());
}
+
+ [Test]
+ public void TestGridSizeToggling()
+ {
+ AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
+ AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
+ gridSizeIs(4);
+
+ nextGridSizeIs(8);
+ nextGridSizeIs(16);
+ nextGridSizeIs(32);
+ nextGridSizeIs(4);
+ }
+
+ private void nextGridSizeIs(int size)
+ {
+ AddStep("toggle to next grid size", () => InputManager.Key(Key.G));
+ gridSizeIs(size);
+ }
+
+ private void gridSizeIs(int size)
+ => AddAssert($"grid size is {size}", () => this.ChildrenOfType().Single().Spacing == new Vector2(size));
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index 491ad655fa..a2ee646341 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -17,7 +17,6 @@ using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
-using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Components.TernaryButtons;
using osu.Game.Screens.Edit.Compose.Components;
@@ -309,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Edit
if (gridSnapToggle.Value == TernaryState.True)
{
- rectangularPositionSnapGridContainer.Add(rectangularPositionSnapGrid = new RectangularPositionSnapGrid(OsuPlayfield.BASE_SIZE / 2, new Vector2(16))
+ rectangularPositionSnapGridContainer.Add(rectangularPositionSnapGrid = new OsuRectangularPositionSnapGrid(EditorBeatmap.BeatmapInfo.GridSize)
{
RelativeSizeAxes = Axes.Both
});
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
new file mode 100644
index 0000000000..2faaab75e4
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
@@ -0,0 +1,50 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Osu.UI;
+using osu.Game.Screens.Edit.Compose.Components;
+using osuTK;
+using osuTK.Input;
+
+namespace osu.Game.Rulesets.Osu.Edit
+{
+ public class OsuRectangularPositionSnapGrid : RectangularPositionSnapGrid
+ {
+ private static readonly int[] grid_sizes = { 4, 8, 16, 32 };
+
+ private int currentGridSizeIndex;
+
+ public OsuRectangularPositionSnapGrid(int gridSize)
+ : base(OsuPlayfield.BASE_SIZE / 2)
+ {
+ var gridSizeIndex = Array.IndexOf(grid_sizes, gridSize);
+ if (gridSizeIndex > 0)
+ currentGridSizeIndex = gridSizeIndex;
+ updateSpacing();
+ }
+
+ protected override bool OnKeyDown(KeyDownEvent e)
+ {
+ if (e.Key == Key.G)
+ {
+ nextGridSize();
+ return true;
+ }
+
+ return false;
+ }
+
+ private void nextGridSize()
+ {
+ currentGridSizeIndex = (currentGridSizeIndex + 1) % grid_sizes.Length;
+ updateSpacing();
+ }
+
+ private void updateSpacing()
+ {
+ Spacing = new Vector2(grid_sizes[currentGridSizeIndex]);
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
index ec267bf752..85a98eca47 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs
@@ -49,9 +49,10 @@ namespace osu.Game.Tests.Visual.Editing
{
RectangularPositionSnapGrid grid = null;
- AddStep("create grid", () => Child = grid = new RectangularPositionSnapGrid(position, spacing)
+ AddStep("create grid", () => Child = grid = new RectangularPositionSnapGrid(position)
{
- RelativeSizeAxes = Axes.Both
+ RelativeSizeAxes = Axes.Both,
+ Spacing = spacing
});
AddStep("add snapping cursor", () => Add(new SnappingCursorContainer
diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
index f243c027e3..95b4b2fe53 100644
--- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs
@@ -17,17 +17,29 @@ namespace osu.Game.Screens.Edit.Compose.Components
///
public Vector2 StartPosition { get; }
+ private Vector2 spacing = Vector2.One;
+
///
/// The spacing between grid lines of this .
///
- public Vector2 Spacing { get; }
+ public Vector2 Spacing
+ {
+ get => spacing;
+ set
+ {
+ if (spacing.X <= 0 || spacing.Y <= 0)
+ throw new ArgumentException("Grid spacing must be positive.");
+
+ spacing = value;
+ gridCache.Invalidate();
+ }
+ }
private readonly LayoutValue gridCache = new LayoutValue(Invalidation.RequiredParentSizeToFit);
- public RectangularPositionSnapGrid(Vector2 startPosition, Vector2 spacing)
+ public RectangularPositionSnapGrid(Vector2 startPosition)
{
StartPosition = startPosition;
- Spacing = spacing;
AddLayout(gridCache);
}
From cdef6d0cf56a633c77d9b28ca2166d19eeb52a51 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Sep 2021 16:43:15 +0900
Subject: [PATCH 34/56] Add key binding support for grid mode cycle
---
.../Edit/OsuRectangularPositionSnapGrid.cs | 32 +++++++++++--------
.../Input/Bindings/GlobalActionContainer.cs | 6 +++-
.../GlobalActionKeyBindingStrings.cs | 5 +++
3 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
index 2faaab75e4..da18d3175e 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
@@ -2,15 +2,16 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
+using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
-using osuTK.Input;
namespace osu.Game.Rulesets.Osu.Edit
{
- public class OsuRectangularPositionSnapGrid : RectangularPositionSnapGrid
+ public class OsuRectangularPositionSnapGrid : RectangularPositionSnapGrid, IKeyBindingHandler
{
private static readonly int[] grid_sizes = { 4, 8, 16, 32 };
@@ -25,17 +26,6 @@ namespace osu.Game.Rulesets.Osu.Edit
updateSpacing();
}
- protected override bool OnKeyDown(KeyDownEvent e)
- {
- if (e.Key == Key.G)
- {
- nextGridSize();
- return true;
- }
-
- return false;
- }
-
private void nextGridSize()
{
currentGridSizeIndex = (currentGridSizeIndex + 1) % grid_sizes.Length;
@@ -46,5 +36,21 @@ namespace osu.Game.Rulesets.Osu.Edit
{
Spacing = new Vector2(grid_sizes[currentGridSizeIndex]);
}
+
+ public bool OnPressed(KeyBindingPressEvent e)
+ {
+ switch (e.Action)
+ {
+ case GlobalAction.EditorCycleGridDisplayMode:
+ nextGridSize();
+ return true;
+ }
+
+ return false;
+ }
+
+ public void OnReleased(KeyBindingReleaseEvent e)
+ {
+ }
}
}
diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
index f62131e2d7..9fd7caadd0 100644
--- a/osu.Game/Input/Bindings/GlobalActionContainer.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -75,6 +75,7 @@ namespace osu.Game.Input.Bindings
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.A }, GlobalAction.EditorVerifyMode),
new KeyBinding(new[] { InputKey.J }, GlobalAction.EditorNudgeLeft),
new KeyBinding(new[] { InputKey.K }, GlobalAction.EditorNudgeRight),
+ new KeyBinding(new[] { InputKey.G }, GlobalAction.EditorCycleGridDisplayMode),
};
public IEnumerable InGameKeyBindings => new[]
@@ -284,6 +285,9 @@ namespace osu.Game.Input.Bindings
SeekReplayBackward,
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleChatFocus))]
- ToggleChatFocus
+ ToggleChatFocus,
+
+ [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCycleGridDisplayMode))]
+ EditorCycleGridDisplayMode
}
}
diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs
index 14159f0d34..06f1b094bf 100644
--- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs
+++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs
@@ -164,6 +164,11 @@ namespace osu.Game.Localisation
///
public static LocalisableString EditorTimingMode => new TranslatableString(getKey(@"editor_timing_mode"), @"Timing mode");
+ ///
+ /// "Cycle grid display mode"
+ ///
+ public static LocalisableString EditorCycleGridDisplayMode => new TranslatableString(getKey(@"editor_cycle_grid_display_mode"), @"Cycle grid display mode");
+
///
/// "Hold for HUD"
///
From a3464c98a7b11826694eddf3587399a9ec7ce648 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Sep 2021 23:51:58 +0900
Subject: [PATCH 35/56] Fix `KeyCounterDisplay` potentially getting stuck
invisible due to autosize masking
Closes #14793.
---
osu.Game/Screens/Play/KeyCounterDisplay.cs | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs
index 2ed4afafd3..66a44e5314 100644
--- a/osu.Game/Screens/Play/KeyCounterDisplay.cs
+++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs
@@ -33,8 +33,6 @@ namespace osu.Game.Screens.Play
public KeyCounterDisplay()
{
- AutoSizeAxes = Axes.Both;
-
InternalChild = KeyFlow = new FillFlowContainer
{
Direction = FillDirection.Horizontal,
@@ -42,6 +40,15 @@ namespace osu.Game.Screens.Play
};
}
+ protected override void Update()
+ {
+ base.Update();
+
+ // Don't use autosize as it will shrink to zero when KeyFlow is hidden.
+ // In turn this can cause the display to be masked off screen and never become visible again.
+ Size = KeyFlow.Size;
+ }
+
public override void Add(KeyCounter key)
{
if (key == null) throw new ArgumentNullException(nameof(key));
From b5af01f4561757857e5863b1b306efb11f1049f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Sep 2021 20:13:06 +0200
Subject: [PATCH 36/56] Always show rectangular grid in osu! composer
---
.../Edit/OsuHitObjectComposer.cs | 22 +++----------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index a2ee646341..3e4711db58 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
RelativeSizeAxes = Axes.Both
},
- rectangularPositionSnapGridContainer = new Container
+ rectangularPositionSnapGrid = new OsuRectangularPositionSnapGrid(EditorBeatmap.BeatmapInfo.GridSize)
{
RelativeSizeAxes = Axes.Both
}
@@ -89,8 +89,6 @@ namespace osu.Game.Rulesets.Osu.Edit
gridSnapToggle.ValueChanged += _ =>
{
- updateRectangularPositionSnapGrid();
-
if (gridSnapToggle.Value == TernaryState.True)
distanceSnapToggle.Value = TernaryState.False;
};
@@ -111,6 +109,8 @@ namespace osu.Game.Rulesets.Osu.Edit
private readonly Cached distanceSnapGridCache = new Cached();
private double? lastDistanceSnapGridTime;
+ private RectangularPositionSnapGrid rectangularPositionSnapGrid;
+
protected override void Update()
{
base.Update();
@@ -298,21 +298,5 @@ namespace osu.Game.Rulesets.Osu.Edit
return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject);
}
-
- private Container rectangularPositionSnapGridContainer;
- private RectangularPositionSnapGrid rectangularPositionSnapGrid;
-
- private void updateRectangularPositionSnapGrid()
- {
- rectangularPositionSnapGridContainer.Clear();
-
- if (gridSnapToggle.Value == TernaryState.True)
- {
- rectangularPositionSnapGridContainer.Add(rectangularPositionSnapGrid = new OsuRectangularPositionSnapGrid(EditorBeatmap.BeatmapInfo.GridSize)
- {
- RelativeSizeAxes = Axes.Both
- });
- }
- }
}
}
From 52542374e8bb07b5e2e76a408adb1139313b9b62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Sep 2021 20:14:28 +0200
Subject: [PATCH 37/56] Fix rectangular grid snap being always active
---
osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index 3e4711db58..027334ba8b 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -42,12 +42,12 @@ namespace osu.Game.Rulesets.Osu.Edit
};
private readonly Bindable distanceSnapToggle = new Bindable();
- private readonly Bindable gridSnapToggle = new Bindable();
+ private readonly Bindable rectangularGridSnapToggle = new Bindable();
protected override IEnumerable CreateTernaryButtons() => base.CreateTernaryButtons().Concat(new[]
{
new TernaryButton(distanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Ruler }),
- new TernaryButton(gridSnapToggle, "Grid Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Th })
+ new TernaryButton(rectangularGridSnapToggle, "Grid Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Th })
});
private BindableList selectedHitObjects;
@@ -84,12 +84,12 @@ namespace osu.Game.Rulesets.Osu.Edit
updateDistanceSnapGrid();
if (distanceSnapToggle.Value == TernaryState.True)
- gridSnapToggle.Value = TernaryState.False;
+ rectangularGridSnapToggle.Value = TernaryState.False;
};
- gridSnapToggle.ValueChanged += _ =>
+ rectangularGridSnapToggle.ValueChanged += _ =>
{
- if (gridSnapToggle.Value == TernaryState.True)
+ if (rectangularGridSnapToggle.Value == TernaryState.True)
distanceSnapToggle.Value = TernaryState.False;
};
@@ -142,13 +142,13 @@ namespace osu.Game.Rulesets.Osu.Edit
if (positionSnap.ScreenSpacePosition != screenSpacePosition)
return positionSnap;
- if (distanceSnapGrid != null)
+ if (distanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null)
{
(Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition));
return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time, PlayfieldAtScreenSpacePosition(screenSpacePosition));
}
- if (rectangularPositionSnapGrid != null)
+ if (rectangularGridSnapToggle.Value == TernaryState.True)
{
Vector2 pos = rectangularPositionSnapGrid.GetSnappedPosition(rectangularPositionSnapGrid.ToLocalSpace(screenSpacePosition));
return new SnapResult(rectangularPositionSnapGrid.ToScreenSpace(pos), null, PlayfieldAtScreenSpacePosition(screenSpacePosition));
From fe21577f113d89d2d648442c53f19dfcf5fb657a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Sep 2021 20:32:34 +0200
Subject: [PATCH 38/56] Adjust grid snap in line with new logic
---
.../Editor/TestSceneOsuEditorGrids.cs | 25 +++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
index 81e44a57db..77aac54929 100644
--- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -4,7 +4,9 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
+using osu.Framework.Utils;
using osu.Game.Rulesets.Osu.Edit;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Tests.Visual;
using osuTK;
using osuTK.Input;
@@ -21,14 +23,33 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType().Any());
+ rectangularGridActive(false);
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType().Any());
- AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
+ rectangularGridActive(true);
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
+ AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType().Any());
- AddUntilStep("rectangular grid hidden", () => !this.ChildrenOfType().Any());
+ rectangularGridActive(false);
+ }
+
+ private void rectangularGridActive(bool active)
+ {
+ AddStep("choose placement tool", () => InputManager.Key(Key.Number2));
+ AddStep("move cursor to (1, 1)", () =>
+ {
+ var composer = Editor.ChildrenOfType().Single();
+ InputManager.MoveMouseTo(composer.ToScreenSpace(new Vector2(1, 1)));
+ });
+
+ if (active)
+ AddAssert("placement blueprint at (0, 0)", () => Precision.AlmostEquals(Editor.ChildrenOfType().Single().HitObject.Position, new Vector2(0, 0)));
+ else
+ AddAssert("placement blueprint at (1, 1)", () => Precision.AlmostEquals(Editor.ChildrenOfType().Single().HitObject.Position, new Vector2(1, 1)));
+
+ AddStep("choose selection tool", () => InputManager.Key(Key.Number1));
}
[Test]
From 0d7dac03f439c1333ef2572ae8590728bfa1934b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Sep 2021 20:34:22 +0200
Subject: [PATCH 39/56] Start with largest grid size
---
osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs | 4 ++--
osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
index 77aac54929..00813dee3a 100644
--- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -57,12 +57,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
{
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
- gridSizeIs(4);
+ gridSizeIs(32);
+ nextGridSizeIs(4);
nextGridSizeIs(8);
nextGridSizeIs(16);
nextGridSizeIs(32);
- nextGridSizeIs(4);
}
private void nextGridSizeIs(int size)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
index da18d3175e..74cb49bedc 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
private static readonly int[] grid_sizes = { 4, 8, 16, 32 };
- private int currentGridSizeIndex;
+ private int currentGridSizeIndex = grid_sizes.Length - 1;
public OsuRectangularPositionSnapGrid(int gridSize)
: base(OsuPlayfield.BASE_SIZE / 2)
From d15bd5a15e7c293dfa5a58a0049c0b74de024a37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Sep 2021 20:39:39 +0200
Subject: [PATCH 40/56] Store grid size back to beatmap on change
---
.../Editor/TestSceneOsuEditorGrids.cs | 3 ++-
.../Edit/OsuHitObjectComposer.cs | 2 +-
.../Edit/OsuRectangularPositionSnapGrid.cs | 19 ++++++++++++++++---
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
index 00813dee3a..a24cb6526d 100644
--- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -72,6 +72,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
}
private void gridSizeIs(int size)
- => AddAssert($"grid size is {size}", () => this.ChildrenOfType().Single().Spacing == new Vector2(size));
+ => AddAssert($"grid size is {size}", () => this.ChildrenOfType().Single().Spacing == new Vector2(size)
+ && EditorBeatmap.BeatmapInfo.GridSize == size);
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index 027334ba8b..1e84ec80e1 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
RelativeSizeAxes = Axes.Both
},
- rectangularPositionSnapGrid = new OsuRectangularPositionSnapGrid(EditorBeatmap.BeatmapInfo.GridSize)
+ rectangularPositionSnapGrid = new OsuRectangularPositionSnapGrid
{
RelativeSizeAxes = Axes.Both
}
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
index 74cb49bedc..b93585af09 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
@@ -2,10 +2,12 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using osu.Framework.Allocation;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Osu.UI;
+using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@@ -17,10 +19,18 @@ namespace osu.Game.Rulesets.Osu.Edit
private int currentGridSizeIndex = grid_sizes.Length - 1;
- public OsuRectangularPositionSnapGrid(int gridSize)
+ [Resolved]
+ private EditorBeatmap editorBeatmap { get; set; }
+
+ public OsuRectangularPositionSnapGrid()
: base(OsuPlayfield.BASE_SIZE / 2)
{
- var gridSizeIndex = Array.IndexOf(grid_sizes, gridSize);
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ var gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize);
if (gridSizeIndex > 0)
currentGridSizeIndex = gridSizeIndex;
updateSpacing();
@@ -34,7 +44,10 @@ namespace osu.Game.Rulesets.Osu.Edit
private void updateSpacing()
{
- Spacing = new Vector2(grid_sizes[currentGridSizeIndex]);
+ int gridSize = grid_sizes[currentGridSizeIndex];
+
+ editorBeatmap.BeatmapInfo.GridSize = gridSize;
+ Spacing = new Vector2(gridSize);
}
public bool OnPressed(KeyBindingPressEvent e)
From bad3f0b1e9f0af33a45e4e3624605b51ab995f4d Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 14:25:44 +0900
Subject: [PATCH 41/56] Disable FtB pass for particle spewer
---
osu.Game/Graphics/ParticleSpewer.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/osu.Game/Graphics/ParticleSpewer.cs b/osu.Game/Graphics/ParticleSpewer.cs
index 466bf04369..54a2b1e890 100644
--- a/osu.Game/Graphics/ParticleSpewer.cs
+++ b/osu.Game/Graphics/ParticleSpewer.cs
@@ -164,6 +164,8 @@ namespace osu.Game.Graphics
return Vector2Extensions.Transform(new Vector2(x, y), DrawInfo.Matrix);
}
+
+ protected override bool CanDrawOpaqueInterior => false;
}
#endregion
From 6246bbc262eb789099b515a3dd2d20cf54607e14 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 14:37:09 +0900
Subject: [PATCH 42/56] Also add to ParticleExplosion
---
osu.Game/Graphics/ParticleExplosion.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/osu.Game/Graphics/ParticleExplosion.cs b/osu.Game/Graphics/ParticleExplosion.cs
index e0d2b50c55..094cc87bbe 100644
--- a/osu.Game/Graphics/ParticleExplosion.cs
+++ b/osu.Game/Graphics/ParticleExplosion.cs
@@ -115,6 +115,8 @@ namespace osu.Game.Graphics
null, TextureCoords);
}
}
+
+ protected override bool CanDrawOpaqueInterior => false;
}
private readonly struct ParticlePart
From f0971cb90c43a50fe3c5b2c1185e9e3eb56335f8 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 14:40:33 +0900
Subject: [PATCH 43/56] Fix kiai spawner using wrong current time
---
osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
index 2b0dfba1dd..9a7eb6835b 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
@@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
DrawableHitObject kiaiHitObject = null;
// Check whether currently in a kiai section first. This is only done as an optimisation to avoid enumerating AliveObjects when not necessary.
- if (gameplayBeatmap.ControlPointInfo.EffectPointAt(gameplayBeatmap.Time.Current).KiaiMode)
+ if (gameplayBeatmap.ControlPointInfo.EffectPointAt(Time.Current).KiaiMode)
kiaiHitObject = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(isTracking);
kiaiSpewer.Active.Value = kiaiHitObject != null;
From 69e28dc8a1bbd9edabd79dd1a69be7e1803f5124 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 14:44:22 +0900
Subject: [PATCH 44/56] Add failing test
---
osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs
index 11b1f5b2af..bd39dead34 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs
@@ -98,6 +98,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{
var controlPointInfo = new ControlPointInfo();
controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true });
+ controlPointInfo.Add(5000, new EffectControlPoint { KiaiMode = false });
return new Beatmap
{
From 6c91d39c15a0e6f4c563dac9e3b0a83537a187db Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 14:48:41 +0900
Subject: [PATCH 45/56] Remove GameplayClock dependency
---
osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
index 9a7eb6835b..c2db5f3f82 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs
@@ -39,9 +39,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
[Resolved(canBeNull: true)]
private GameplayBeatmap gameplayBeatmap { get; set; }
- [Resolved(canBeNull: true)]
- private GameplayClock gameplayClock { get; set; }
-
[BackgroundDependencyLoader]
private void load(ISkinSource skin, OsuColour colours)
{
From 430ecc5409a903a1f871c3097a24c92beb3ff6f0 Mon Sep 17 00:00:00 2001
From: smoogipoo
Date: Tue, 21 Sep 2021 15:20:04 +0900
Subject: [PATCH 46/56] Adjust to make HD slightly harder and not obsolete
---
osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index b3a54521d8..7f565cb82d 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -22,13 +22,13 @@ namespace osu.Game.Rulesets.Taiko.Mods
/// How far away from the hit target should hitobjects start to fade out.
/// Range: [0, 1]
///
- private const float fade_out_start_time = 0.6f;
+ private const float fade_out_start_time = 1f;
///
/// How long hitobjects take to fade out, in terms of the scrolling length.
/// Range: [0, 1]
///
- private const float fade_out_duration = 0.3f;
+ private const float fade_out_duration = 0.375f;
private DrawableTaikoRuleset drawableRuleset;
From 5c7fe5dde0fdc861f48d1741c01d8312e52ce3b3 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Sep 2021 14:23:44 +0900
Subject: [PATCH 47/56] Retarget `master` repos in diffcalc CI runs
---
.github/workflows/diffcalc.yml | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml
index 842522ae87..3c57d971ae 100644
--- a/.github/workflows/diffcalc.yml
+++ b/.github/workflows/diffcalc.yml
@@ -78,8 +78,7 @@ jobs:
- name: Checkout osu (master)
uses: actions/checkout@v2
with:
- repository: peppy/osu
- ref: 'diffcalc-optimisations'
+ repository: ppy/osu
path: 'master/osu'
- name: Checkout osu (pr)
uses: actions/checkout@v2
@@ -89,14 +88,12 @@ jobs:
- name: Checkout osu-difficulty-calculator (master)
uses: actions/checkout@v2
with:
- repository: peppy/osu-difficulty-calculator
- ref: 'bypass-attrib-row-insert'
+ repository: ppy/osu-difficulty-calculator
path: 'master/osu-difficulty-calculator'
- name: Checkout osu-difficulty-calculator (pr)
uses: actions/checkout@v2
with:
- repository: peppy/osu-difficulty-calculator
- ref: 'bypass-attrib-row-insert'
+ repository: ppy/osu-difficulty-calculator
path: 'pr/osu-difficulty-calculator'
- name: Install .NET 5.0.x
From 59d6a718d66eb39d81a3ad067354d1cbabb1c4b9 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Sep 2021 20:09:34 +0900
Subject: [PATCH 48/56] Fix value not being loaded from beatmap in case of most
dense grid setting
---
osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
index b93585af09..b8ff92bd37 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs
@@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Edit
private void load()
{
var gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize);
- if (gridSizeIndex > 0)
+ if (gridSizeIndex >= 0)
currentGridSizeIndex = gridSizeIndex;
updateSpacing();
}
From 4cdce69f7e7c7b365c386f580def615723749658 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Sep 2021 23:45:03 +0900
Subject: [PATCH 49/56] Update test to match test beamap data
---
osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
index a24cb6526d..47b2d3a098 100644
--- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs
@@ -57,12 +57,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
{
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
AddUntilStep("rectangular grid visible", () => this.ChildrenOfType().Any());
- gridSizeIs(32);
+ gridSizeIs(4);
- nextGridSizeIs(4);
nextGridSizeIs(8);
nextGridSizeIs(16);
nextGridSizeIs(32);
+ nextGridSizeIs(4);
}
private void nextGridSizeIs(int size)
From 77660d904820d2e632054a19ba1f1ec2ce36d5e5 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Wed, 22 Sep 2021 01:13:47 +0900
Subject: [PATCH 50/56] Update diffcalc action to checkout the correct upstream
branch
---
.github/workflows/diffcalc.yml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml
index 3c57d971ae..9e6d1c9f71 100644
--- a/.github/workflows/diffcalc.yml
+++ b/.github/workflows/diffcalc.yml
@@ -74,16 +74,23 @@ jobs:
mkdir -p $GITHUB_WORKSPACE/master/
mkdir -p $GITHUB_WORKSPACE/pr/
+ - name: Get upstream branch # https://akaimo.hatenablog.jp/entry/2020/05/16/101251
+ id: upstreambranch
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ echo "::set-output name=branchname::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')"
+
# Checkout osu
- name: Checkout osu (master)
uses: actions/checkout@v2
with:
- repository: ppy/osu
path: 'master/osu'
- name: Checkout osu (pr)
uses: actions/checkout@v2
with:
path: 'pr/osu'
+ ref: ${{ steps.upstreambranch.outputs.branchname }}
- name: Checkout osu-difficulty-calculator (master)
uses: actions/checkout@v2
From d22fcc14fc3cfb095a17a392cee666bb7a8ba5ad Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Wed, 22 Sep 2021 01:28:17 +0900
Subject: [PATCH 51/56] Also grab correct repository path
---
.github/workflows/diffcalc.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml
index 9e6d1c9f71..35fd45320c 100644
--- a/.github/workflows/diffcalc.yml
+++ b/.github/workflows/diffcalc.yml
@@ -80,6 +80,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "::set-output name=branchname::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')"
+ echo "::set-output name=repo::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.repo.full_name' | sed 's/\"//g')"
# Checkout osu
- name: Checkout osu (master)
@@ -90,6 +91,7 @@ jobs:
uses: actions/checkout@v2
with:
path: 'pr/osu'
+ repository: $${{ steps.upstreambranch.outputs.repo }}
ref: ${{ steps.upstreambranch.outputs.branchname }}
- name: Checkout osu-difficulty-calculator (master)
From 29d69b2b83742246fddee1a208128bb53d5de913 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Wed, 22 Sep 2021 01:29:56 +0900
Subject: [PATCH 52/56] Remove extra $
---
.github/workflows/diffcalc.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml
index 35fd45320c..bc2626d3d6 100644
--- a/.github/workflows/diffcalc.yml
+++ b/.github/workflows/diffcalc.yml
@@ -91,7 +91,7 @@ jobs:
uses: actions/checkout@v2
with:
path: 'pr/osu'
- repository: $${{ steps.upstreambranch.outputs.repo }}
+ repository: ${{ steps.upstreambranch.outputs.repo }}
ref: ${{ steps.upstreambranch.outputs.branchname }}
- name: Checkout osu-difficulty-calculator (master)
From dcadf3b81dd7c012ffac4749778eb1a3cb081160 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Thu, 23 Sep 2021 19:18:51 +0900
Subject: [PATCH 53/56] Add failing test coverage of some dialogs being held on
to
---
.../UserInterface/TestSceneDialogOverlay.cs | 23 +++++++++++--------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs
index f5cba2c900..405461eec8 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs
@@ -24,9 +24,10 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test]
public void TestBasic()
{
- TestPopupDialog dialog = null;
+ TestPopupDialog firstDialog = null;
+ TestPopupDialog secondDialog = null;
- AddStep("dialog #1", () => overlay.Push(dialog = new TestPopupDialog
+ AddStep("dialog #1", () => overlay.Push(firstDialog = new TestPopupDialog
{
Icon = FontAwesome.Regular.TrashAlt,
HeaderText = @"Confirm deletion of",
@@ -46,9 +47,9 @@ namespace osu.Game.Tests.Visual.UserInterface
},
}));
- AddAssert("first dialog displayed", () => overlay.CurrentDialog == dialog);
+ AddAssert("first dialog displayed", () => overlay.CurrentDialog == firstDialog);
- AddStep("dialog #2", () => overlay.Push(dialog = new TestPopupDialog
+ AddStep("dialog #2", () => overlay.Push(secondDialog = new TestPopupDialog
{
Icon = FontAwesome.Solid.Cog,
HeaderText = @"What do you want to do with",
@@ -82,30 +83,33 @@ namespace osu.Game.Tests.Visual.UserInterface
},
}));
- AddAssert("second dialog displayed", () => overlay.CurrentDialog == dialog);
+ AddAssert("second dialog displayed", () => overlay.CurrentDialog == secondDialog);
+ AddAssert("first dialog is not part of hierarchy", () => firstDialog.Parent == null);
}
[Test]
public void TestDismissBeforePush()
{
+ TestPopupDialog testDialog = null;
AddStep("dismissed dialog push", () =>
{
- overlay.Push(new TestPopupDialog
+ overlay.Push(testDialog = new TestPopupDialog
{
State = { Value = Visibility.Hidden }
});
});
AddAssert("no dialog pushed", () => overlay.CurrentDialog == null);
+ AddAssert("dialog is not part of hierarchy", () => testDialog.Parent == null);
}
[Test]
public void TestDismissBeforePushViaButtonPress()
{
+ TestPopupDialog testDialog = null;
AddStep("dismissed dialog push", () =>
{
- TestPopupDialog dialog;
- overlay.Push(dialog = new TestPopupDialog
+ overlay.Push(testDialog = new TestPopupDialog
{
Buttons = new PopupDialogButton[]
{
@@ -113,10 +117,11 @@ namespace osu.Game.Tests.Visual.UserInterface
},
});
- dialog.PerformOkAction();
+ testDialog.PerformOkAction();
});
AddAssert("no dialog pushed", () => overlay.CurrentDialog == null);
+ AddAssert("dialog is not part of hierarchy", () => testDialog.Parent == null);
}
private class TestPopupDialog : PopupDialog
From 6b698047ab7dc0f937bcb61669ed326e990be51d Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Thu, 23 Sep 2021 19:19:03 +0900
Subject: [PATCH 54/56] Fix `DialogOverlay` potentially not expiring dialogs as
soon as it should
---
osu.Game/Overlays/DialogOverlay.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs
index d5d31343f2..f051e09c08 100644
--- a/osu.Game/Overlays/DialogOverlay.cs
+++ b/osu.Game/Overlays/DialogOverlay.cs
@@ -49,6 +49,8 @@ namespace osu.Game.Overlays
Show();
}
+ public override bool IsPresent => dialogContainer.Children.Count > 0;
+
protected override bool BlockNonPositionalInput => true;
private void onDialogOnStateChanged(VisibilityContainer dialog, Visibility v)
From ad6c4e38784cfaee12b7b4f232b8d5e673eca293 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Fri, 24 Sep 2021 12:46:46 +0900
Subject: [PATCH 55/56] Update framework
---
osu.Android.props | 2 +-
osu.Game/osu.Game.csproj | 2 +-
osu.iOS.props | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/osu.Android.props b/osu.Android.props
index 4859510e6c..967405cd2e 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index e6afbe383a..61ae6aa69e 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 51ca381b63..e032926a9c 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
-
+
@@ -93,7 +93,7 @@
-
+
From 9b9c30c8a13bfa6b724f691d5c2b11dd76078a68 Mon Sep 17 00:00:00 2001
From: Joseph Madamba
Date: Fri, 24 Sep 2021 21:57:52 -0700
Subject: [PATCH 56/56] Fix text overflowing on dropdown headers
---
.../Graphics/UserInterface/OsuDropdown.cs | 39 ++++++++++++++-----
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs
index 42f628a75a..fe88e6f78a 100644
--- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs
+++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs
@@ -274,21 +274,40 @@ namespace osu.Game.Graphics.UserInterface
CornerRadius = corner_radius;
Height = 40;
- Foreground.Children = new Drawable[]
+ Foreground.Child = new GridContainer
{
- Text = new OsuSpriteText
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ RowDimensions = new[]
{
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
+ new Dimension(GridSizeMode.AutoSize),
},
- Icon = new SpriteIcon
+ ColumnDimensions = new[]
{
- Icon = FontAwesome.Solid.ChevronDown,
- Anchor = Anchor.CentreRight,
- Origin = Anchor.CentreRight,
- Margin = new MarginPadding { Right = 5 },
- Size = new Vector2(12),
+ new Dimension(),
+ new Dimension(GridSizeMode.AutoSize),
},
+ Content = new[]
+ {
+ new Drawable[]
+ {
+ Text = new OsuSpriteText
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ RelativeSizeAxes = Axes.X,
+ Truncate = true,
+ },
+ Icon = new SpriteIcon
+ {
+ Icon = FontAwesome.Solid.ChevronDown,
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ Margin = new MarginPadding { Horizontal = 5 },
+ Size = new Vector2(12),
+ },
+ }
+ }
};
AddInternal(new HoverClickSounds());