Skip to content

Commit 48ae8ac

Browse files
Merge upstream/master and fix TestFruitColourFallback colour comparison
- Merge 7 upstream ppy/osu commits (prioritizing our fork's package versions) - Fix TestFruitColourFallback: use tolerance-based colour comparison to handle float precision loss through ColourInfo/SRGBColour roundtrip - Resolve merge conflicts in osu.Game.csproj, ModSelectFooterContent.cs, FooterButtonMods.cs (keeping our framework 2026.526.1 and Veldrid.SPIRV pin) Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
2 parents 4e8a2b0 + e3eeb76 commit 48ae8ac

53 files changed

Lines changed: 1103 additions & 237 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

osu.Game.Benchmarks/BenchmarkScoreMultiplierCalculator.cs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,7 @@ public record ModTestCase(string Description, IEnumerable<Mod> Mods)
4242
public override void SetUp()
4343
{
4444
base.SetUp();
45-
calculator = new OsuRuleset().CreateScoreMultiplierCalculator();
46-
}
47-
48-
[Benchmark]
49-
public double ViaModScoreMultiplier() => viaModScoreMultiplier(Times, Mods);
50-
51-
[Test]
52-
public void ViaModScoreMultiplier([Values(100)] int times, [ValueSource(nameof(ValuesForMods))] ModTestCase mods)
53-
=> viaModScoreMultiplier(times, mods);
54-
55-
private double viaModScoreMultiplier(int times, ModTestCase mods)
56-
{
57-
double scoreMultiplier = 1;
58-
59-
for (int i = 0; i < times; ++i)
60-
{
61-
scoreMultiplier = 1;
62-
63-
foreach (var mod in mods.Mods)
64-
scoreMultiplier *= mod.ScoreMultiplier;
65-
}
66-
67-
return scoreMultiplier;
45+
calculator = new OsuRuleset().CreateScoreMultiplierCalculator(new ScoreMultiplierContext());
6846
}
6947

7048
[Benchmark]

osu.Game.Rulesets.Catch.Tests/CatchScoreMultiplierTest.cs

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using NUnit.Framework;
55
using osu.Game.Rulesets.Catch.Mods;
6+
using osu.Game.Rulesets.Mods;
67
using osu.Game.Tests.Rulesets;
78

89
namespace osu.Game.Rulesets.Catch.Tests
@@ -14,28 +15,141 @@ public CatchScoreMultiplierTest()
1415
{
1516
}
1617

17-
[Test]
18-
public void TestFlashlightOnNonDefaultSettings()
19-
=> TestModCombination([new CatchModFlashlight { ComboBasedSize = { Value = false } }]);
18+
private static readonly object[][] test_cases =
19+
[
20+
#region Difficulty Reduction
2021

21-
[Test]
22-
public void TestHalfTimeSpeeds([Values(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 0.99)] double speedChange)
23-
=> TestModCombination([new CatchModHalfTime { SpeedChange = { Value = speedChange } }]);
22+
[new Mod[] { new CatchModEasy() }, 0.5],
23+
[new Mod[] { new CatchModNoFail() }, 0.5],
2424

25-
[Test]
26-
public void TestDaycoreSpeeds([Values(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 0.99)] double speedChange)
27-
=> TestModCombination([new CatchModDaycore { SpeedChange = { Value = speedChange } }]);
25+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.50 } } }, 0.1],
26+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.55 } } }, 0.1],
27+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.60 } } }, 0.2],
28+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.65 } } }, 0.2],
29+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.70 } } }, 0.3],
30+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.75 } } }, 0.3],
31+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.80 } } }, 0.4],
32+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.85 } } }, 0.4],
33+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.90 } } }, 0.5],
34+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.95 } } }, 0.5],
35+
[new Mod[] { new CatchModHalfTime { SpeedChange = { Value = 0.99 } } }, 0.5],
2836

29-
[Test]
30-
public void TestDoubleTimeSpeeds([Values(1.01, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2)] double speedChange)
31-
=> TestModCombination([new CatchModDoubleTime { SpeedChange = { Value = speedChange } }]);
37+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.50 } } }, 0.1],
38+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.55 } } }, 0.1],
39+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.60 } } }, 0.2],
40+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.65 } } }, 0.2],
41+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.70 } } }, 0.3],
42+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.75 } } }, 0.3],
43+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.80 } } }, 0.4],
44+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.85 } } }, 0.4],
45+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.90 } } }, 0.5],
46+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.95 } } }, 0.5],
47+
[new Mod[] { new CatchModDaycore { SpeedChange = { Value = 0.99 } } }, 0.5],
3248

33-
[Test]
34-
public void TestNightcoreSpeeds([Values(1.01, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2)] double speedChange)
35-
=> TestModCombination([new CatchModNightcore { SpeedChange = { Value = speedChange } }]);
49+
#endregion
3650

37-
[Test]
38-
public void TestMultiplicativeCombination()
39-
=> TestModCombination([new CatchModHidden(), new CatchModHardRock()]);
51+
#region Difficulty Increase
52+
53+
[new Mod[] { new CatchModHardRock() }, 1.12],
54+
[new Mod[] { new CatchModSuddenDeath() }, 1],
55+
[new Mod[] { new CatchModPerfect() }, 1],
56+
57+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.01 } } }, 1.00],
58+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.05 } } }, 1.00],
59+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.10 } } }, 1.02],
60+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.15 } } }, 1.02],
61+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.20 } } }, 1.04],
62+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.25 } } }, 1.04],
63+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.30 } } }, 1.06],
64+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.35 } } }, 1.06],
65+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.40 } } }, 1.08],
66+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.45 } } }, 1.08],
67+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.50 } } }, 1.10],
68+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.55 } } }, 1.10],
69+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.60 } } }, 1.12],
70+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.65 } } }, 1.12],
71+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.70 } } }, 1.14],
72+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.75 } } }, 1.14],
73+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.80 } } }, 1.16],
74+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.85 } } }, 1.16],
75+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.90 } } }, 1.18],
76+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 1.95 } } }, 1.18],
77+
[new Mod[] { new CatchModDoubleTime { SpeedChange = { Value = 2.00 } } }, 1.20],
78+
79+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.01 } } }, 1.00],
80+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.05 } } }, 1.00],
81+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.10 } } }, 1.02],
82+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.15 } } }, 1.02],
83+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.20 } } }, 1.04],
84+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.25 } } }, 1.04],
85+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.30 } } }, 1.06],
86+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.35 } } }, 1.06],
87+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.40 } } }, 1.08],
88+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.45 } } }, 1.08],
89+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.50 } } }, 1.10],
90+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.55 } } }, 1.10],
91+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.60 } } }, 1.12],
92+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.65 } } }, 1.12],
93+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.70 } } }, 1.14],
94+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.75 } } }, 1.14],
95+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.80 } } }, 1.16],
96+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.85 } } }, 1.16],
97+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.90 } } }, 1.18],
98+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 1.95 } } }, 1.18],
99+
[new Mod[] { new CatchModNightcore { SpeedChange = { Value = 2.00 } } }, 1.20],
100+
101+
[new Mod[] { new CatchModHidden() }, 1.06],
102+
103+
[new Mod[] { new CatchModFlashlight() }, 1.12],
104+
[new Mod[] { new CatchModFlashlight { ComboBasedSize = { Value = false } } }, 1],
105+
106+
[new Mod[] { new ModAccuracyChallenge() }, 1],
107+
108+
#endregion
109+
110+
#region Conversion
111+
112+
[new Mod[] { new CatchModDifficultyAdjust() }, 0.5],
113+
[new Mod[] { new CatchModClassic() }, 0.96],
114+
[new Mod[] { new CatchModMirror() }, 1],
115+
116+
#endregion
117+
118+
#region Automation
119+
120+
[new Mod[] { new CatchModAutoplay() }, 1],
121+
[new Mod[] { new CatchModCinema() }, 1],
122+
[new Mod[] { new CatchModRelax() }, 0.1],
123+
124+
#endregion
125+
126+
#region Fun
127+
128+
[new Mod[] { new ModWindUp() }, 0.5],
129+
[new Mod[] { new ModWindDown() }, 0.5],
130+
[new Mod[] { new CatchModFloatingFruits() }, 1],
131+
[new Mod[] { new CatchModMuted() }, 1],
132+
[new Mod[] { new CatchModNoScope() }, 1],
133+
[new Mod[] { new CatchModMovingFast() }, 1],
134+
[new Mod[] { new CatchModSynesthesia() }, 0.8],
135+
136+
#endregion
137+
138+
#region System
139+
140+
[new Mod[] { new ModScoreV2() }, 1],
141+
142+
#endregion
143+
144+
#region Combinations
145+
146+
[new Mod[] { new CatchModHidden(), new CatchModHardRock() }, 1.06 * 1.12]
147+
148+
#endregion
149+
];
150+
151+
[TestCaseSource(nameof(test_cases))]
152+
public void TestMultipliers(Mod[] mods, double expectedMultiplier)
153+
=> TestModCombination(mods, expectedMultiplier);
40154
}
41155
}

osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#nullable disable
55

6+
using System;
67
using System.Linq;
78
using System.Numerics;
89
using NUnit.Framework;
@@ -197,7 +198,13 @@ private Drawable setupSkinHierarchy(Drawable child, ISkin skin)
197198

198199
private bool checkLegacyFruitHyperDashColour(DrawableFruit fruit, Colour4 expectedColour) =>
199200
fruit.ChildrenOfType<SkinnableDrawable>().FirstOrDefault()?.Drawable.ChildrenOfType<Sprite>()
200-
.Any(c => c.Colour == expectedColour) == true;
201+
.Any(c => colourApproximatelyEquals(c.Colour.TopLeft.SRGB, expectedColour)) == true;
202+
203+
private static bool colourApproximatelyEquals(Colour4 actual, Colour4 expected) =>
204+
Math.Abs(actual.R - expected.R) < 0.002f
205+
&& Math.Abs(actual.G - expected.G) < 0.002f
206+
&& Math.Abs(actual.B - expected.B) < 0.002f
207+
&& Math.Abs(actual.A - expected.A) < 0.002f;
201208

202209
private class TestSkin : LegacySkin
203210
{

osu.Game.Rulesets.Catch/CatchRuleset.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public override IEnumerable<Mod> GetModsFor(ModType type)
168168
}
169169
}
170170

171-
public override ScoreMultiplierCalculator CreateScoreMultiplierCalculator() => new CatchScoreMultiplierCalculator();
171+
public override ScoreMultiplierCalculator CreateScoreMultiplierCalculator(ScoreMultiplierContext context) => new CatchScoreMultiplierCalculator(context);
172172

173173
public override string Description => "osu!catch";
174174

osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33

44
using System.Collections.Generic;
55
using System.Linq;
6+
using osu.Framework.Graphics;
7+
using osu.Framework.Graphics.Containers;
8+
using osu.Framework.Graphics.Sprites;
69
using osu.Framework.Input.Events;
10+
using osu.Game.Graphics;
711
using osu.Game.Rulesets.Catch.Edit.Blueprints;
812
using osu.Game.Rulesets.Catch.Objects;
913
using osu.Game.Rulesets.Edit;
1014
using osu.Game.Rulesets.Objects;
15+
using osu.Game.Screens.Edit.Components.TernaryButtons;
1116
using osu.Game.Screens.Edit.Compose.Components;
1217
using System.Numerics;
1318

@@ -22,6 +27,29 @@ public CatchBlueprintContainer(CatchHitObjectComposer composer)
2227
{
2328
}
2429

30+
protected override Drawable CreateNewComboButton() => new NewComboTernaryButton
31+
{
32+
Current = NewCombo,
33+
CreateIcon = () => new Container
34+
{
35+
Children = new Drawable[]
36+
{
37+
new SpriteIcon
38+
{
39+
Anchor = Anchor.BottomLeft,
40+
Origin = Anchor.BottomLeft,
41+
Icon = OsuIcon.EditorFruit,
42+
Size = new Vector2(15),
43+
},
44+
new SpriteIcon
45+
{
46+
Icon = OsuIcon.EditorNewComboSparkles,
47+
Size = new Vector2(20),
48+
}
49+
},
50+
},
51+
};
52+
2553
protected override SelectionHandler<HitObject> CreateSelectionHandler() => new CatchSelectionHandler();
2654

2755
public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject)

osu.Game.Rulesets.Catch/Scoring/CatchScoreMultiplierCalculator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ namespace osu.Game.Rulesets.Catch.Scoring
99
{
1010
public class CatchScoreMultiplierCalculator : ScoreMultiplierCalculator
1111
{
12-
static CatchScoreMultiplierCalculator()
12+
public CatchScoreMultiplierCalculator(ScoreMultiplierContext context)
13+
: base(context)
1314
{
1415
#region Difficulty Reduction
1516

0 commit comments

Comments
 (0)