From 7d1e73e36dcf67a5052395aa84f9c241d2d6696b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 21:24:31 +0200 Subject: [PATCH 01/19] Add workflow for automated osu-web mod definition updates --- .../workflows/update-web-mod-definitions.yml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/update-web-mod-definitions.yml diff --git a/.github/workflows/update-web-mod-definitions.yml b/.github/workflows/update-web-mod-definitions.yml new file mode 100644 index 0000000000..32d3d37ffe --- /dev/null +++ b/.github/workflows/update-web-mod-definitions.yml @@ -0,0 +1,53 @@ +name: Update osu-web mod definitions +on: + push: + tags: + - '*' + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + update-mod-definitions: + name: Update osu-web mod definitions + runs-on: ubuntu-latest + steps: + - name: Install .NET 6.0.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: "6.0.x" + + - name: Checkout ppy/osu + uses: actions/checkout@v3 + with: + path: osu + + - name: Checkout ppy/osu-tools + uses: actions/checkout@v3 + with: + repository: ppy/osu-tools + path: osu-tools + + - name: Checkout ppy/osu-web + uses: actions/checkout@v3 + with: + repository: ppy/osu-web + path: osu-web + + - name: Setup local game checkout for tools + run: ./UseLocalOsu.sh + working-directory: ./osu-tools + + - name: Regenerate mod definitions + run: dotnet run --project PerformanceCalculator -- mods > ../osu-web/database/mods.json + working-directory: ./osu-tools + + - name: Create pull request with changes + uses: peter-evans/create-pull-request@v5 + with: + title: Update mod definitions + body: "This PR has been auto-generated to update the mod definitions to match ppy/osu@${{ github.ref_name }}." + branch: update-mod-definitions + commit-message: Update mod definitions + path: osu-web + token: ${{ secrets.OSU_WEB_PULL_REQUEST_PAT }} From f7d44c3013f3bb11d6e2aa5476950e1d4036f3ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 12:32:38 +0900 Subject: [PATCH 02/19] Rename `SliderMultiplier` to `BaseSliderVelocity` --- .../Editor/TestSceneJuiceStreamPlacementBlueprint.cs | 2 +- .../Editor/TestSceneJuiceStreamSelectionBlueprint.cs | 2 +- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 4 ++-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Editor/TestSceneSliderStreamConversion.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Editor/TestSceneTaikoEditorSaving.cs | 4 ++-- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- .../Mods/TaikoModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 2 +- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 2 +- .../TestSceneHitObjectComposerDistanceSnapping.cs | 12 ++++++------ .../Visual/Editing/TestSceneDistanceSnapGrid.cs | 2 +- .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 4 ++-- .../Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- osu.Game/Beatmaps/BeatmapDifficulty.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs | 7 ++++--- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 6 +++--- 30 files changed, 49 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index 2426f8c886..e729a09a18 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor { var playable = base.GetPlayableBeatmap(); playable.Difficulty.SliderTickRate = 5; - playable.Difficulty.SliderMultiplier = velocity_factor * 10; + playable.Difficulty.BaseSliderVelocity = velocity_factor * 10; return playable; } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index beba5811fe..634e1f5cbb 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor X = x, Path = sliderPath, }; - EditorBeatmap.Difficulty.SliderMultiplier = velocity; + EditorBeatmap.Difficulty.BaseSliderVelocity = velocity; EditorBeatmap.Add(hitObject); EditorBeatmap.Update(hitObject); Assert.That(hitObject.Velocity, Is.EqualTo(velocity)); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 40dc7d2403..d1f3f06971 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index c91f07891c..71cb8964c3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 }, + Difficulty = new BeatmapDifficulty { CircleSize = 5, BaseSliderVelocity = 2 }, Ruleset = ruleset }, HitObjects = new List diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 169e99c90c..301ecd6d66 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Catch.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - velocityFactor = base_scoring_distance * difficulty.SliderMultiplier / timingPoint.BeatLength; - tickDistanceFactor = base_scoring_distance * difficulty.SliderMultiplier / difficulty.SliderTickRate; + velocityFactor = base_scoring_distance * difficulty.BaseSliderVelocity / timingPoint.BeatLength; + tickDistanceFactor = base_scoring_distance * difficulty.BaseSliderVelocity / difficulty.SliderTickRate; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 91b7be6e8f..ab6f5e8269 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy StartTime = (int)Math.Round(hitObject.StartTime); // This matches stable's calculation. - EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.SliderMultiplier); + EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.BaseSliderVelocity); SegmentDuration = (EndTime - StartTime) / SpanCount; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index af8758fb5e..cb38551a43 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Mania doesn't care about global velocity p.Velocity = 1; - p.BaseBeatLength *= Beatmap.Difficulty.SliderMultiplier; + p.BaseBeatLength *= Beatmap.Difficulty.BaseSliderVelocity; // For non-mania beatmap, speed changes should only happen through timing points if (!isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index 7579e8077b..b79d4efe1b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [SetUp] public void Setup() => Schedule(() => { - editorBeatmap.Difficulty.SliderMultiplier = 1; + editorBeatmap.Difficulty.BaseSliderVelocity = 1; editorBeatmap.ControlPointInfo.Clear(); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); snapProvider.DistanceSpacingMultiplier.Value = 1; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index a162d9a491..938e093489 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("change to these specific circumstances", () => { - EditorBeatmap.Difficulty.SliderMultiplier = 1; + EditorBeatmap.Difficulty.BaseSliderVelocity = 1; var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(slider.StartTime); timingPoint.BeatLength = 352.941176470588; slider.Path.ControlPoints[^1].Position = new Vector2(-110, 16); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4189f8ba1e..b86351e7cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index 93b26624de..d79ca28c8f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor [Test] public void TestTaikoSliderMultiplier() { - AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.BaseSliderVelocity = 2); SaveEditor(); @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor // therefore, ensure that we have that difficulty type by calling .CopyFrom(), which is a no-op if the type is already correct. var taikoDifficulty = new TaikoBeatmapConverter.TaikoMultiplierAppliedDifficulty(); taikoDifficulty.CopyFrom(EditorBeatmap.Difficulty); - return Precision.AlmostEquals(taikoDifficulty.SliderMultiplier, 2); + return Precision.AlmostEquals(taikoDifficulty.BaseSliderVelocity, 2); } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index e298e313df..932211695a 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps else beatLength = timingPoint.BeatLength; - double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate; + double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.BaseSliderVelocity / beatmap.Difficulty.SliderTickRate; // The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll. double taikoVelocity = sliderScoringPointDistance * beatmap.Difficulty.SliderTickRate; @@ -239,14 +239,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { base.CopyTo(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - other.SliderMultiplier /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + other.BaseSliderVelocity /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } public override void CopyFrom(IBeatmapDifficultyInfo other) { base.CopyFrom(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + BaseSliderVelocity *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } #endregion diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 99a064d35f..fe9c1f5815 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { base.ApplySettings(difficulty); - if (ScrollSpeed.Value != null) difficulty.SliderMultiplier *= ScrollSpeed.Value.Value; + if (ScrollSpeed.Value != null) difficulty.BaseSliderVelocity *= ScrollSpeed.Value.Value; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 009f2854f8..5aeb5a87d7 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.SliderMultiplier *= slider_multiplier; + difficulty.BaseSliderVelocity *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index ba41175461..0f68750535 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.SliderMultiplier *= slider_multiplier; + difficulty.BaseSliderVelocity *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index b4a12fd314..014fec9319 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = base_distance * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; tickSpacing = timingPoint.BeatLength / TickRate; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 2c4f193327..98ad6fc18d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.SliderMultiplier); + Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); Assert.AreEqual(2, difficulty.SliderTickRate); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 3764467047..11c5f2a2fc 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.SliderMultiplier); + Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); Assert.AreEqual(2, difficulty.SliderTickRate); } diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index 6399507aa0..ffbe16260b 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Editing BeatDivisor.Value = 1; - composer.EditorBeatmap.Difficulty.SliderMultiplier = 1; + composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 1; composer.EditorBeatmap.ControlPointInfo.Clear(); composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); }); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSliderMultiplier(float multiplier) { - AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier); + AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = multiplier); assertSnapDistance(100 * multiplier, null, true); } @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Editing assertDurationToDistance(500, 50); assertDurationToDistance(1000, 100); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertDurationToDistance(500, 100); assertDurationToDistance(1000, 200); @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Editing assertDistanceToDuration(50, 500); assertDistanceToDuration(100, 1000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertDistanceToDuration(100, 500); assertDistanceToDuration(200, 1000); @@ -174,7 +174,7 @@ namespace osu.Game.Tests.Editing assertSnappedDuration(200, 2000); assertSnappedDuration(250, 3000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertSnappedDuration(0, 0); assertSnappedDuration(50, 0); @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Editing assertSnappedDistance(200, 200); assertSnappedDistance(250, 200); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertSnappedDistance(50, 0); assertSnappedDistance(100, 0); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index 21b925a257..a99bd72e40 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Editing } }); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); - editorBeatmap.Difficulty.SliderMultiplier = 1; + editorBeatmap.Difficulty.BaseSliderVelocity = 1; } [SetUp] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 287b7d43b4..735af9493c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.SliderMultiplier = 2; + beatmap.Difficulty.BaseSliderVelocity = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.SliderMultiplier = 2; + beatmap.Difficulty.BaseSliderVelocity = 2; createTest(beatmap); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 114c554d28..28cc890fce 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, Ruleset = ruleset }, ControlPointInfo = controlPointInfo diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index f4bc5e7b77..cbea30f3b0 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// public const float DEFAULT_DIFFICULTY = 5; @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps public float OverallDifficulty { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; public float ApproachRate { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; - public double SliderMultiplier { get; set; } = 1; + public double BaseSliderVelocity { get; set; } = 1; public double SliderTickRate { get; set; } = 1; public BeatmapDifficulty() @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps difficulty.CircleSize = CircleSize; difficulty.OverallDifficulty = OverallDifficulty; - difficulty.SliderMultiplier = SliderMultiplier; + difficulty.BaseSliderVelocity = BaseSliderVelocity; difficulty.SliderTickRate = SliderTickRate; } @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps CircleSize = other.CircleSize; OverallDifficulty = other.OverallDifficulty; - SliderMultiplier = other.SliderMultiplier; + BaseSliderVelocity = other.BaseSliderVelocity; SliderTickRate = other.SliderTickRate; } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 4731a70753..e96e38d249 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -353,7 +353,7 @@ namespace osu.Game.Beatmaps CircleSize = decodedDifficulty.CircleSize, OverallDifficulty = decodedDifficulty.OverallDifficulty, ApproachRate = decodedDifficulty.ApproachRate, - SliderMultiplier = decodedDifficulty.SliderMultiplier, + BaseSliderVelocity = decodedDifficulty.BaseSliderVelocity, SliderTickRate = decodedDifficulty.SliderTickRate, }; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 5e98025c9a..891e627435 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,7 +384,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); + difficulty.BaseSliderVelocity = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 7fbcca9adb..fffead3a6c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -155,8 +155,8 @@ namespace osu.Game.Beatmaps.Formats // Taiko adjusts the slider multiplier (see: LEGACY_TAIKO_VELOCITY_MULTIPLIER) writer.WriteLine(onlineRulesetID == 1 - ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") - : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier}")); + ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") + : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity}")); writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.Difficulty.SliderTickRate}")); } diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index dad9bbbd0b..bc2ee23da7 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps public interface IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// const float DEFAULT_DIFFICULTY = 5; @@ -34,9 +34,10 @@ namespace osu.Game.Beatmaps float ApproachRate { get; } /// - /// The slider multiplier of the associated beatmap. + /// The base slider velocity of the associated beatmap. + /// This was known as "SliderMultiplier" in the .osu format and stable editor. /// - double SliderMultiplier { get; } + double BaseSliderVelocity { get; } /// /// The slider tick rate of the associated beatmap. diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index a8972775de..4adbb356da 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 + return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.BaseSliderVelocity * 1 / BeatSnapProvider.BeatDivisor); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 7ddd372dc9..bdcf539033 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Objects.Legacy TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = base_scoring_distance * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 4c7564b791..da1110506a 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.UI.Scrolling // The slider multiplier is post-multiplied to determine the final velocity, but for relative scale beat lengths // the multiplier should not affect the effective timing point (the longest in the beatmap), so it is factored out here - baseBeatLength /= Beatmap.Difficulty.SliderMultiplier; + baseBeatLength /= Beatmap.Difficulty.BaseSliderVelocity; } // Merge sequences of timing and difficulty control points to create the aggregate "multiplier" control point @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.UI.Scrolling return new MultiplierControlPoint(c.Time) { - Velocity = Beatmap.Difficulty.SliderMultiplier, + Velocity = Beatmap.Difficulty.BaseSliderVelocity, BaseBeatLength = baseBeatLength, TimingPoint = lastTimingPoint, EffectPoint = lastEffectPoint @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.UI.Scrolling ControlPoints.AddRange(timingChanges); if (ControlPoints.Count == 0) - ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.SliderMultiplier }); + ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.BaseSliderVelocity }); } protected override void LoadComplete() From b109ee74a631a32df7195b077cd237e70ead1530 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:20:57 +0900 Subject: [PATCH 03/19] Add "base velocity" adjustment to difficulty setup screen --- osu.Game/Localisation/EditorSetupStrings.cs | 10 ++++++++++ osu.Game/Screens/Edit/Setup/DifficultySection.cs | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/osu.Game/Localisation/EditorSetupStrings.cs b/osu.Game/Localisation/EditorSetupStrings.cs index 4ddacf2c5b..caea3dd130 100644 --- a/osu.Game/Localisation/EditorSetupStrings.cs +++ b/osu.Game/Localisation/EditorSetupStrings.cs @@ -126,6 +126,16 @@ namespace osu.Game.Localisation public static LocalisableString OverallDifficultyDescription => new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + /// + /// "Base Velocity" + /// + public static LocalisableString BaseVelocity => new TranslatableString(getKey(@"base_velocity"), @"Base Velocity"); + + /// + /// "The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets." + /// + public static LocalisableString BaseVelocityDescription => new TranslatableString(getKey(@"base_velocity_description"), @"The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets."); + /// /// "Metadata" /// diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 7026bde681..7c4b0e72d7 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Edit.Setup private LabelledSliderBar healthDrainSlider = null!; private LabelledSliderBar approachRateSlider = null!; private LabelledSliderBar overallDifficultySlider = null!; + private LabelledSliderBar baseVelocitySlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; @@ -79,6 +80,19 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, + baseVelocitySlider = new LabelledSliderBar + { + Label = EditorSetupStrings.BaseVelocity, + FixedLabelWidth = LABEL_WIDTH, + Description = EditorSetupStrings.BaseVelocityDescription, + Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) + { + Default = 1, + MinValue = 0.01, + MaxValue = 10, + Precision = 0.1f, + } + }, }; foreach (var item in Children.OfType>()) @@ -93,6 +107,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; + Beatmap.Difficulty.BaseSliderVelocity = baseVelocitySlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 31de4de72031afdfa1e02ed201a5bbcacf9d8333 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:21:39 +0900 Subject: [PATCH 04/19] Remove median/mode slider velocity display The intention was to give an idea of what the most common velocity of the beatmap is, but in hindsight, because the "base" velocity is being set elsewhere this doesn't make sense. It will/should be 1.0x. Showing this range is still valuable, though. --- .../Timeline/DifficultyPointPiece.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 13a1c30cfe..545e54254a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -159,20 +159,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray(); - if (sliderVelocities.Length < 2) - return; + if (sliderVelocities.First() != sliderVelocities.Last()) + { + AddHeader("Used velocity range"); + AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); + } - double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key; - double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2]; - - AddHeader("Average velocity"); - AddValue($"{medianSliderVelocity:#,0.00}x"); - - AddHeader("Most used velocity"); - AddValue($"{modeSliderVelocity:#,0.00}x"); - - AddHeader("Velocity range"); - AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); } protected override void Dispose(bool isDisposing) From d9dd35c0202d10694721737c16675e4db236c45f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:22:48 +0900 Subject: [PATCH 05/19] Show base velocity in slider adjustment popover --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 545e54254a..a02a3be430 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -165,6 +165,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); } + AddHeader("Beatmap base velocity"); + AddValue($"{EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x"); } protected override void Dispose(bool isDisposing) From 451af9d1b5b04e58cf034f65a2480366c3b9a34b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:23:13 +0900 Subject: [PATCH 06/19] Fix beatmap values not being updated due to a varying data type --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 7c4b0e72d7..66bb8a9b84 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -96,10 +96,13 @@ namespace osu.Game.Screens.Edit.Setup }; foreach (var item in Children.OfType>()) - item.Current.ValueChanged += onValueChanged; + item.Current.ValueChanged += _ => updateValues(); + + foreach (var item in Children.OfType>()) + item.Current.ValueChanged += _ => updateValues(); } - private void onValueChanged(ValueChangedEvent args) + private void updateValues() { // for now, update these on commit rather than making BeatmapMetadata bindables. // after switching database engines we can reconsider if switching to bindables is a good direction. From a91edd68d976df038c654feea6c1714d03ac11bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:42:25 +0900 Subject: [PATCH 07/19] Show post-multiplied velocity in main hit object inspector --- osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index 597925e3e2..60b9010aa8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (selected is IHasSliderVelocity sliderVelocity) { AddHeader("Slider Velocity"); - AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x"); + AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x)"); } if (selected is IHasRepeats repeats) From a6cb1f90e4c9ab1b2e06bda043321f2795a56b8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:43:21 +0900 Subject: [PATCH 08/19] Change difficulty popover inspector display (yet again) I think this makes the most sense of the iterations I've tested so far, albeit maybe being a touch too verbose. --- .../Timeline/DifficultyPointPiece.cs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index a02a3be430..ac37101060 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.X, Text = "Hold shift while dragging the end of an object to adjust velocity while snapping." }, - new SliderVelocityInspector(), + new SliderVelocityInspector(sliderVelocitySlider.Current), } } }; @@ -145,28 +145,48 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline internal partial class SliderVelocityInspector : EditorInspector { + private readonly Bindable current; + + public SliderVelocityInspector(Bindable current) + { + this.current = current; + } + [BackgroundDependencyLoader] private void load() { EditorBeatmap.TransactionBegan += updateInspectorText; EditorBeatmap.TransactionEnded += updateInspectorText; + EditorBeatmap.BeatmapReprocessed += updateInspectorText; + current.ValueChanged += _ => updateInspectorText(); + updateInspectorText(); } private void updateInspectorText() { + double beatmapVelocity = EditorBeatmap.Difficulty.BaseSliderVelocity; + InspectorText.Clear(); double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray(); + AddHeader("Base velocity (from beatmap setup)"); + AddValue($"{beatmapVelocity:#,0.00}x"); + + AddHeader("Final velocity"); + AddValue($"{beatmapVelocity * current.Value:#,0.00}x"); + if (sliderVelocities.First() != sliderVelocities.Last()) { - AddHeader("Used velocity range"); - AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); - } + AddHeader("Beatmap velocity range"); - AddHeader("Beatmap base velocity"); - AddValue($"{EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x"); + string range = $"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"; + if (beatmapVelocity != 1) + range += $" ({beatmapVelocity * sliderVelocities.First():#,0.00}x - {beatmapVelocity * sliderVelocities.Last():#,0.00}x)"; + + AddValue(range); + } } protected override void Dispose(bool isDisposing) From 8c44d528e9f640d56a4834cb81d99cbf81bc630a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:51:52 +0900 Subject: [PATCH 09/19] Use min/max values from stable --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 66bb8a9b84..6c7e96f91d 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -88,9 +88,9 @@ namespace osu.Game.Screens.Edit.Setup Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) { Default = 1, - MinValue = 0.01, - MaxValue = 10, - Precision = 0.1f, + MinValue = 0.4, + MaxValue = 3.6, + Precision = 0.01f, } }, }; From 944da06c108b9240190c297b5825365e10ccf49b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 May 2023 16:58:19 +0900 Subject: [PATCH 10/19] Rename slider multiplier variable back for now --- .../Editor/TestSceneJuiceStreamPlacementBlueprint.cs | 2 +- .../Editor/TestSceneJuiceStreamSelectionBlueprint.cs | 2 +- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 4 ++-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Editor/TestSceneSliderStreamConversion.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Editor/TestSceneTaikoEditorSaving.cs | 4 ++-- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- .../Mods/TaikoModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 2 +- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 2 +- .../TestSceneHitObjectComposerDistanceSnapping.cs | 12 ++++++------ .../Visual/Editing/TestSceneDistanceSnapGrid.cs | 2 +- .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 4 ++-- .../Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- osu.Game/Beatmaps/BeatmapDifficulty.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs | 4 ++-- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 6 +++--- .../Edit/Compose/Components/HitObjectInspector.cs | 2 +- .../Components/Timeline/DifficultyPointPiece.cs | 2 +- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 4 ++-- 33 files changed, 51 insertions(+), 51 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index e729a09a18..2426f8c886 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor { var playable = base.GetPlayableBeatmap(); playable.Difficulty.SliderTickRate = 5; - playable.Difficulty.BaseSliderVelocity = velocity_factor * 10; + playable.Difficulty.SliderMultiplier = velocity_factor * 10; return playable; } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index 634e1f5cbb..beba5811fe 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor X = x, Path = sliderPath, }; - EditorBeatmap.Difficulty.BaseSliderVelocity = velocity; + EditorBeatmap.Difficulty.SliderMultiplier = velocity; EditorBeatmap.Add(hitObject); EditorBeatmap.Update(hitObject); Assert.That(hitObject.Velocity, Is.EqualTo(velocity)); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index d1f3f06971..40dc7d2403 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index 71cb8964c3..c91f07891c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 5, BaseSliderVelocity = 2 }, + Difficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 }, Ruleset = ruleset }, HitObjects = new List diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 301ecd6d66..169e99c90c 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Catch.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - velocityFactor = base_scoring_distance * difficulty.BaseSliderVelocity / timingPoint.BeatLength; - tickDistanceFactor = base_scoring_distance * difficulty.BaseSliderVelocity / difficulty.SliderTickRate; + velocityFactor = base_scoring_distance * difficulty.SliderMultiplier / timingPoint.BeatLength; + tickDistanceFactor = base_scoring_distance * difficulty.SliderMultiplier / difficulty.SliderTickRate; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index ab6f5e8269..91b7be6e8f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy StartTime = (int)Math.Round(hitObject.StartTime); // This matches stable's calculation. - EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.BaseSliderVelocity); + EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.SliderMultiplier); SegmentDuration = (EndTime - StartTime) / SpanCount; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index cb38551a43..af8758fb5e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Mania doesn't care about global velocity p.Velocity = 1; - p.BaseBeatLength *= Beatmap.Difficulty.BaseSliderVelocity; + p.BaseBeatLength *= Beatmap.Difficulty.SliderMultiplier; // For non-mania beatmap, speed changes should only happen through timing points if (!isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index b79d4efe1b..7579e8077b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [SetUp] public void Setup() => Schedule(() => { - editorBeatmap.Difficulty.BaseSliderVelocity = 1; + editorBeatmap.Difficulty.SliderMultiplier = 1; editorBeatmap.ControlPointInfo.Clear(); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); snapProvider.DistanceSpacingMultiplier.Value = 1; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index 938e093489..a162d9a491 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("change to these specific circumstances", () => { - EditorBeatmap.Difficulty.BaseSliderVelocity = 1; + EditorBeatmap.Difficulty.SliderMultiplier = 1; var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(slider.StartTime); timingPoint.BeatLength = 352.941176470588; slider.Path.ControlPoints[^1].Position = new Vector2(-110, 16); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index b86351e7cd..4189f8ba1e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = BASE_SCORING_DISTANCE * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index d79ca28c8f..93b26624de 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor [Test] public void TestTaikoSliderMultiplier() { - AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.SliderMultiplier = 2); SaveEditor(); @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor // therefore, ensure that we have that difficulty type by calling .CopyFrom(), which is a no-op if the type is already correct. var taikoDifficulty = new TaikoBeatmapConverter.TaikoMultiplierAppliedDifficulty(); taikoDifficulty.CopyFrom(EditorBeatmap.Difficulty); - return Precision.AlmostEquals(taikoDifficulty.BaseSliderVelocity, 2); + return Precision.AlmostEquals(taikoDifficulty.SliderMultiplier, 2); } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 932211695a..e298e313df 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps else beatLength = timingPoint.BeatLength; - double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.BaseSliderVelocity / beatmap.Difficulty.SliderTickRate; + double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate; // The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll. double taikoVelocity = sliderScoringPointDistance * beatmap.Difficulty.SliderTickRate; @@ -239,14 +239,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { base.CopyTo(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - other.BaseSliderVelocity /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + other.SliderMultiplier /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } public override void CopyFrom(IBeatmapDifficultyInfo other) { base.CopyFrom(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - BaseSliderVelocity *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } #endregion diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index fe9c1f5815..99a064d35f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { base.ApplySettings(difficulty); - if (ScrollSpeed.Value != null) difficulty.BaseSliderVelocity *= ScrollSpeed.Value.Value; + if (ScrollSpeed.Value != null) difficulty.SliderMultiplier *= ScrollSpeed.Value.Value; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 5aeb5a87d7..009f2854f8 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.BaseSliderVelocity *= slider_multiplier; + difficulty.SliderMultiplier *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 0f68750535..ba41175461 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.BaseSliderVelocity *= slider_multiplier; + difficulty.SliderMultiplier *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 014fec9319..b4a12fd314 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_distance * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; tickSpacing = timingPoint.BeatLength / TickRate; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 98ad6fc18d..2c4f193327 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); + Assert.AreEqual(1.8, difficulty.SliderMultiplier); Assert.AreEqual(2, difficulty.SliderTickRate); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 11c5f2a2fc..3764467047 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); + Assert.AreEqual(1.8, difficulty.SliderMultiplier); Assert.AreEqual(2, difficulty.SliderTickRate); } diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index ffbe16260b..6399507aa0 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Editing BeatDivisor.Value = 1; - composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 1; + composer.EditorBeatmap.Difficulty.SliderMultiplier = 1; composer.EditorBeatmap.ControlPointInfo.Clear(); composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); }); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSliderMultiplier(float multiplier) { - AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = multiplier); + AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier); assertSnapDistance(100 * multiplier, null, true); } @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Editing assertDurationToDistance(500, 50); assertDurationToDistance(1000, 100); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertDurationToDistance(500, 100); assertDurationToDistance(1000, 200); @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Editing assertDistanceToDuration(50, 500); assertDistanceToDuration(100, 1000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertDistanceToDuration(100, 500); assertDistanceToDuration(200, 1000); @@ -174,7 +174,7 @@ namespace osu.Game.Tests.Editing assertSnappedDuration(200, 2000); assertSnappedDuration(250, 3000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertSnappedDuration(0, 0); assertSnappedDuration(50, 0); @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Editing assertSnappedDistance(200, 200); assertSnappedDistance(250, 200); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertSnappedDistance(50, 0); assertSnappedDistance(100, 0); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index a99bd72e40..21b925a257 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Editing } }); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); - editorBeatmap.Difficulty.BaseSliderVelocity = 1; + editorBeatmap.Difficulty.SliderMultiplier = 1; } [SetUp] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 735af9493c..287b7d43b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.BaseSliderVelocity = 2; + beatmap.Difficulty.SliderMultiplier = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.BaseSliderVelocity = 2; + beatmap.Difficulty.SliderMultiplier = 2; createTest(beatmap); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 28cc890fce..114c554d28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, Ruleset = ruleset }, ControlPointInfo = controlPointInfo diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index cbea30f3b0..f4bc5e7b77 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// public const float DEFAULT_DIFFICULTY = 5; @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps public float OverallDifficulty { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; public float ApproachRate { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; - public double BaseSliderVelocity { get; set; } = 1; + public double SliderMultiplier { get; set; } = 1; public double SliderTickRate { get; set; } = 1; public BeatmapDifficulty() @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps difficulty.CircleSize = CircleSize; difficulty.OverallDifficulty = OverallDifficulty; - difficulty.BaseSliderVelocity = BaseSliderVelocity; + difficulty.SliderMultiplier = SliderMultiplier; difficulty.SliderTickRate = SliderTickRate; } @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps CircleSize = other.CircleSize; OverallDifficulty = other.OverallDifficulty; - BaseSliderVelocity = other.BaseSliderVelocity; + SliderMultiplier = other.SliderMultiplier; SliderTickRate = other.SliderTickRate; } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index e96e38d249..4731a70753 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -353,7 +353,7 @@ namespace osu.Game.Beatmaps CircleSize = decodedDifficulty.CircleSize, OverallDifficulty = decodedDifficulty.OverallDifficulty, ApproachRate = decodedDifficulty.ApproachRate, - BaseSliderVelocity = decodedDifficulty.BaseSliderVelocity, + SliderMultiplier = decodedDifficulty.SliderMultiplier, SliderTickRate = decodedDifficulty.SliderTickRate, }; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 891e627435..5e98025c9a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,7 +384,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.BaseSliderVelocity = Parsing.ParseDouble(pair.Value); + difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index fffead3a6c..7fbcca9adb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -155,8 +155,8 @@ namespace osu.Game.Beatmaps.Formats // Taiko adjusts the slider multiplier (see: LEGACY_TAIKO_VELOCITY_MULTIPLIER) writer.WriteLine(onlineRulesetID == 1 - ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") - : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity}")); + ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") + : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier}")); writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.Difficulty.SliderTickRate}")); } diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index bc2ee23da7..78234a9dd9 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps public interface IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// const float DEFAULT_DIFFICULTY = 5; @@ -37,7 +37,7 @@ namespace osu.Game.Beatmaps /// The base slider velocity of the associated beatmap. /// This was known as "SliderMultiplier" in the .osu format and stable editor. /// - double BaseSliderVelocity { get; } + double SliderMultiplier { get; } /// /// The slider tick rate of the associated beatmap. diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index 4adbb356da..a8972775de 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.BaseSliderVelocity * 1 + return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index bdcf539033..7ddd372dc9 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Objects.Legacy TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index da1110506a..4c7564b791 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.UI.Scrolling // The slider multiplier is post-multiplied to determine the final velocity, but for relative scale beat lengths // the multiplier should not affect the effective timing point (the longest in the beatmap), so it is factored out here - baseBeatLength /= Beatmap.Difficulty.BaseSliderVelocity; + baseBeatLength /= Beatmap.Difficulty.SliderMultiplier; } // Merge sequences of timing and difficulty control points to create the aggregate "multiplier" control point @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.UI.Scrolling return new MultiplierControlPoint(c.Time) { - Velocity = Beatmap.Difficulty.BaseSliderVelocity, + Velocity = Beatmap.Difficulty.SliderMultiplier, BaseBeatLength = baseBeatLength, TimingPoint = lastTimingPoint, EffectPoint = lastEffectPoint @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.UI.Scrolling ControlPoints.AddRange(timingChanges); if (ControlPoints.Count == 0) - ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.BaseSliderVelocity }); + ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.SliderMultiplier }); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index 60b9010aa8..7beaf7d086 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (selected is IHasSliderVelocity sliderVelocity) { AddHeader("Slider Velocity"); - AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x)"); + AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.SliderMultiplier:#,0.00}x)"); } if (selected is IHasRepeats repeats) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index ac37101060..76ad3e5b6a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateInspectorText() { - double beatmapVelocity = EditorBeatmap.Difficulty.BaseSliderVelocity; + double beatmapVelocity = EditorBeatmap.Difficulty.SliderMultiplier; InspectorText.Clear(); diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 6c7e96f91d..3a3fe7f747 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Edit.Setup Label = EditorSetupStrings.BaseVelocity, FixedLabelWidth = LABEL_WIDTH, Description = EditorSetupStrings.BaseVelocityDescription, - Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) + Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier) { Default = 1, MinValue = 0.4, @@ -110,7 +110,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; - Beatmap.Difficulty.BaseSliderVelocity = baseVelocitySlider.Current.Value; + Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 2085833a842c023ddb26e85e6fd54a2375867119 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 May 2023 17:08:03 +0900 Subject: [PATCH 11/19] Fix missing delegate unsubscribe --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 76ad3e5b6a..173a665d5c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -195,6 +195,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline EditorBeatmap.TransactionBegan -= updateInspectorText; EditorBeatmap.TransactionEnded -= updateInspectorText; + EditorBeatmap.BeatmapReprocessed -= updateInspectorText; } } } From ca5e8b290f30006c93116e7d1ef47fbdb663fc00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 14:05:59 +0900 Subject: [PATCH 12/19] Add clamping to `SliderMultiplier` and `SliderTickRate` at parsing time --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 5e98025c9a..49594ca969 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,11 +384,11 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); + difficulty.SliderMultiplier = Math.Clamp(Parsing.ParseDouble(pair.Value), 0.4, 3.6); break; case @"SliderTickRate": - difficulty.SliderTickRate = Parsing.ParseDouble(pair.Value); + difficulty.SliderTickRate = Math.Clamp(Parsing.ParseDouble(pair.Value), 0.5, 8); break; } } From bdf8a78b4245dc008e8661820ea3cbcff42b97e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 14:14:54 +0900 Subject: [PATCH 13/19] Add the ability to adjust the beatmap tick rate in the editor --- osu.Game/Localisation/EditorSetupStrings.cs | 31 ++++++++++--------- .../Screens/Edit/Setup/DifficultySection.cs | 15 +++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/osu.Game/Localisation/EditorSetupStrings.cs b/osu.Game/Localisation/EditorSetupStrings.cs index caea3dd130..401411365b 100644 --- a/osu.Game/Localisation/EditorSetupStrings.cs +++ b/osu.Game/Localisation/EditorSetupStrings.cs @@ -42,8 +42,7 @@ namespace osu.Game.Localisation /// /// "If enabled, an "Are you ready? 3, 2, 1, GO!" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so." /// - public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), - @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); + public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); /// /// "Countdown speed" @@ -53,8 +52,7 @@ namespace osu.Game.Localisation /// /// "If the countdown sounds off-time, use this to make it appear one or more beats early." /// - public static LocalisableString CountdownOffsetDescription => - new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); + public static LocalisableString CountdownOffsetDescription => new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); /// /// "Countdown offset" @@ -69,8 +67,7 @@ namespace osu.Game.Localisation /// /// "Allows storyboards to use the full screen space, rather than be confined to a 4:3 area." /// - public static LocalisableString WidescreenSupportDescription => - new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); + public static LocalisableString WidescreenSupportDescription => new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); /// /// "Epilepsy warning" @@ -80,8 +77,7 @@ namespace osu.Game.Localisation /// /// "Recommended if the storyboard or video contain scenes with rapidly flashing colours." /// - public static LocalisableString EpilepsyWarningDescription => - new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); + public static LocalisableString EpilepsyWarningDescription => new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); /// /// "Letterbox during breaks" @@ -91,8 +87,7 @@ namespace osu.Game.Localisation /// /// "Adds horizontal letterboxing to give a cinematic look during breaks." /// - public static LocalisableString LetterboxDuringBreaksDescription => - new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); + public static LocalisableString LetterboxDuringBreaksDescription => new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); /// /// "Samples match playback rate" @@ -102,8 +97,7 @@ namespace osu.Game.Localisation /// /// "When enabled, all samples will speed up or slow down when rate-changing mods are enabled." /// - public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), - @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); + public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); /// /// "The size of all hit objects" @@ -123,8 +117,17 @@ namespace osu.Game.Localisation /// /// "The harshness of hit windows and difficulty of special objects (ie. spinners)" /// - public static LocalisableString OverallDifficultyDescription => - new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + public static LocalisableString OverallDifficultyDescription => new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + + /// + /// "Tick Rate" + /// + public static LocalisableString TickRate => new TranslatableString(getKey(@"tick_rate"), @"Tick Rate"); + + /// + /// "Determines how many "ticks" are generated within long hit objects. A tick rate of 1 will generate ticks on each beat, 2 would be twice per beat, etc." + /// + public static LocalisableString TickRateDescription => new TranslatableString(getKey(@"tick_rate_description"), @"Determines how many ""ticks"" are generated within long hit objects. A tick rate of 1 will generate ticks on each beat, 2 would be twice per beat, etc."); /// /// "Base Velocity" diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 3a3fe7f747..4c062b0cb7 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Edit.Setup private LabelledSliderBar approachRateSlider = null!; private LabelledSliderBar overallDifficultySlider = null!; private LabelledSliderBar baseVelocitySlider = null!; + private LabelledSliderBar tickRateSlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; @@ -93,6 +94,19 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.01f, } }, + tickRateSlider = new LabelledSliderBar + { + Label = EditorSetupStrings.TickRate, + FixedLabelWidth = LABEL_WIDTH, + Description = EditorSetupStrings.TickRateDescription, + Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate) + { + Default = 1, + MinValue = 1, + MaxValue = 4, + Precision = 1, + } + }, }; foreach (var item in Children.OfType>()) @@ -111,6 +125,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value; + Beatmap.Difficulty.SliderTickRate = tickRateSlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 745341ca6b4b5c1ed40b362a2fece9af58a7af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 May 2023 21:55:53 +0200 Subject: [PATCH 14/19] Fix iOS build workflow failing A new version of `Microsoft.iOS.Sdk` was released on 2023-05-09T17:28:41.7300000. This version requires Xcode 14.3, which is not currently available on `macos-latest` runners (which currently alias to `macos-12`). To fix, migrate to `macos-13`, which is currently in beta, and explicitly use Xcode 14.3 (because even on the `macos-13` image, Xcode 14.3 is not yet the default). --- .github/workflows/ci.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e60e0a39ae..a8167ec4db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,12 +121,24 @@ jobs: build-only-ios: name: Build only (iOS) - runs-on: macos-latest + # `macos-13` is required, because Xcode 14.3 is required (see below). + # TODO: can be changed to `macos-latest` once `macos-13` becomes latest (currently in beta) + runs-on: macos-13 timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 + # newest Microsoft.iOS.Sdk versions require Xcode 14.3. + # 14.3 is currently not the default Xcode version (https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode), + # so set it manually. + # TODO: remove when 14.3 becomes the default Xcode version. + - name: Set Xcode version + shell: bash + run: | + sudo xcode-select -s "/Applications/Xcode_14.3.app" + echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.3.app" >> $GITHUB_ENV + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v3 with: From 4aa241daeab7d12eb8a32f1bb1da78ed5749a5c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 May 2023 15:19:43 +0900 Subject: [PATCH 15/19] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e9ecbaa10b..ff76e17184 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7ab9810ab5..93f22a31d8 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 bfa0dc63bb..c5477f765e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 3fc19553b4435211370cfd2655ed35992ae95aa7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 May 2023 15:19:46 +0900 Subject: [PATCH 16/19] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 93f22a31d8..4315f44e07 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From c1a85658b728614be2f25fbca7d8dda1916865f3 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 11 May 2023 14:58:17 +0100 Subject: [PATCH 17/19] feat(settings): add "import" as keywords for first run setup --- osu.Game/Overlays/Settings/Sections/GeneralSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index c5274d6223..b12541b261 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Settings.Sections new SettingsButton { Text = GeneralSettingsStrings.RunSetupWizard, - Keywords = new[] { @"first run", @"initial", @"getting started" }, + Keywords = new[] { @"first run", @"initial", @"getting started", @"import" }, TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, From 2d45d602a538532245f9fe4287700e27493e962b Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 11 May 2023 15:03:42 +0100 Subject: [PATCH 18/19] feat(settings): more keyword for first run setup --- osu.Game/Overlays/Settings/Sections/GeneralSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index b12541b261..f4a79d65e6 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Settings.Sections new SettingsButton { Text = GeneralSettingsStrings.RunSetupWizard, - Keywords = new[] { @"first run", @"initial", @"getting started", @"import" }, + Keywords = new[] { @"first run", @"initial", @"getting started", @"import", @"tutorial", @"recommended beatmaps" }, TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, From 3bce7ac58931806ddaa81191b04e744ffbdef680 Mon Sep 17 00:00:00 2001 From: js1086 Date: Thu, 11 May 2023 19:07:22 +0100 Subject: [PATCH 19/19] Copy SliderVelocity to strict tracking sliders --- osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index 7e4ffc7408..72031b4958 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -98,6 +98,7 @@ namespace osu.Game.Rulesets.Osu.Mods ComboOffset = original.ComboOffset; LegacyLastTickOffset = original.LegacyLastTickOffset; TickDistanceMultiplier = original.TickDistanceMultiplier; + SliderVelocity = original.SliderVelocity; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken)