From 98141430b0cb6d4b45397eadbf8b537020330af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Oct 2024 14:48:07 +0200 Subject: [PATCH 01/15] Add failing tests --- .../Editor/TestSceneManiaSelectionHandler.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs index 4285ef2029..a70b90789d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs @@ -118,5 +118,45 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor AddAssert("all objects in last column", () => EditorBeatmap.HitObjects.All(ho => ((ManiaHitObject)ho).Column == 3)); AddAssert("all objects remain selected", () => EditorBeatmap.SelectedHitObjects.SequenceEqual(EditorBeatmap.HitObjects)); } + + [Test] + public void TestOffScreenObjectsRemainSelectedOnHorizontalFlip() + { + AddStep("create objects", () => + { + for (int i = 0; i < 20; ++i) + EditorBeatmap.Add(new Note { StartTime = 1000 * i, Column = i % 4 }); + }); + + AddStep("select everything", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("flip", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Key(Key.H); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + AddAssert("all objects remain selected", () => EditorBeatmap.SelectedHitObjects.SequenceEqual(EditorBeatmap.HitObjects)); + } + + [Test] + public void TestOffScreenObjectsRemainSelectedOnVerticalFlip() + { + AddStep("create objects", () => + { + for (int i = 0; i < 20; ++i) + EditorBeatmap.Add(new Note { StartTime = 1000 * i, Column = i % 4 }); + }); + + AddStep("select everything", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("flip", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Key(Key.J); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + AddAssert("all objects remain selected", () => EditorBeatmap.SelectedHitObjects.SequenceEqual(EditorBeatmap.HitObjects.Reverse())); + } } } From 59655a18307d018968710e0abc9584ef88ab90dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Oct 2024 14:48:09 +0200 Subject: [PATCH 02/15] Fix flip operations sometimes not preserving selection Closes https://github.com/ppy/osu/issues/30250. --- .../Edit/ManiaSelectionHandler.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 7e0991a4d4..74e616ac3f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -54,9 +54,8 @@ namespace osu.Game.Rulesets.Mania.Edit int firstColumn = flipOverOrigin ? 0 : selectedObjects.Min(ho => ho.Column); int lastColumn = flipOverOrigin ? (int)EditorBeatmap.BeatmapInfo.Difficulty.CircleSize - 1 : selectedObjects.Max(ho => ho.Column); - EditorBeatmap.PerformOnSelection(hitObject => + performOnSelection(maniaObject => { - var maniaObject = (ManiaHitObject)hitObject; maniaPlayfield.Remove(maniaObject); maniaObject.Column = firstColumn + (lastColumn - maniaObject.Column); maniaPlayfield.Add(maniaObject); @@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Edit double selectionStartTime = selectedObjects.Min(ho => ho.StartTime); double selectionEndTime = selectedObjects.Max(ho => ho.GetEndTime()); - EditorBeatmap.PerformOnSelection(hitObject => + performOnSelection(hitObject => { hitObject.StartTime = selectionStartTime + (selectionEndTime - hitObject.GetEndTime()); }); @@ -117,14 +116,21 @@ namespace osu.Game.Rulesets.Mania.Edit columnDelta = Math.Clamp(columnDelta, -minColumn, maniaPlayfield.TotalColumns - 1 - maxColumn); - EditorBeatmap.PerformOnSelection(h => + performOnSelection(h => { maniaPlayfield.Remove(h); - ((ManiaHitObject)h).Column += columnDelta; + h.Column += columnDelta; maniaPlayfield.Add(h); }); + } - // `HitObjectUsageEventBuffer`'s usage transferal flows and the playfield's `SetKeepAlive()` functionality do not combine well with this operation's usage pattern, + private void performOnSelection(Action action) + { + var selectedObjects = EditorBeatmap.SelectedHitObjects.OfType().ToArray(); + + EditorBeatmap.PerformOnSelection(h => action.Invoke((ManiaHitObject)h)); + + // `HitObjectUsageEventBuffer`'s usage transferal flows and the playfield's `SetKeepAlive()` functionality do not combine well with mania's usage patterns, // leading to selections being sometimes partially dropped if some of the objects being moved are off screen // (check blame for detailed explanation). // thus, ensure that selection is preserved manually. From 0cd352cdcbbf918c0199cb9991df5b7ac2550f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 15 Oct 2024 12:39:08 +0200 Subject: [PATCH 03/15] Add failing test case for first tool switch failure scenario --- .../Editor/TestSceneToolSwitching.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs new file mode 100644 index 0000000000..7bb77e3078 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Rulesets.Osu.Tests.Editor +{ + public partial class TestSceneToolSwitching : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + [Test] + public void TestSliderAnchorMoveOperationEndsOnSwitchingTool() + { + var initialPosition = Vector2.Zero; + + AddStep("store original anchor position", () => initialPosition = EditorBeatmap.HitObjects.OfType().First().Path.ControlPoints.ElementAt(1).Position); + AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.OfType().First())); + AddStep("move to second anchor", () => InputManager.MoveMouseTo(this.ChildrenOfType>().ElementAt(1))); + AddStep("start dragging", () => InputManager.PressButton(MouseButton.Left)); + AddStep("drag away", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(0, -200))); + AddStep("switch tool", () => InputManager.PressButton(MouseButton.Button1)); + AddStep("undo", () => Editor.Undo()); + AddAssert("anchor back at original position", + () => EditorBeatmap.HitObjects.OfType().First().Path.ControlPoints.ElementAt(1).Position, + () => Is.EqualTo(initialPosition)); + } + } +} From 2d0e98c951cc514451a759c0263882eab185cbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 15 Oct 2024 12:45:02 +0200 Subject: [PATCH 04/15] Add failing test case for second tool switching failure case Not exact (doesn't reproduce the crash), but will do. --- .../Editor/TestSceneToolSwitching.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs index 7bb77e3078..d5ab349a16 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneToolSwitching.cs @@ -32,5 +32,24 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor () => EditorBeatmap.HitObjects.OfType().First().Path.ControlPoints.ElementAt(1).Position, () => Is.EqualTo(initialPosition)); } + + [Test] + public void TestSliderAnchorCreationOperationEndsOnSwitchingTool() + { + AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.OfType().First())); + AddStep("move to second anchor", () => InputManager.MoveMouseTo(this.ChildrenOfType>().ElementAt(1), new Vector2(-50, 0))); + AddStep("quick-create anchor", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.PressButton(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + AddStep("drag away", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(0, -200))); + AddStep("switch tool", () => InputManager.PressKey(Key.Number3)); + AddStep("drag away further", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(0, -200))); + AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.OfType().First())); + AddStep("undo", () => Editor.Undo()); + AddAssert("slider has three anchors again", () => EditorBeatmap.HitObjects.OfType().First().Path.ControlPoints, () => Has.Count.EqualTo(3)); + } } } From 1a7acbac33967b2eebb056d8c1189a0c5b777997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 15 Oct 2024 12:49:24 +0200 Subject: [PATCH 05/15] Terminate existing anchor drag operations when object is deselected --- .../Sliders/Components/PathControlPointVisualiser.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 70ccbdfdc4..f114516300 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -333,6 +333,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.Dispose(isDisposing); foreach (var p in Pieces) p.ControlPoint.Changed -= controlPointChanged; + + if (draggedControlPointIndex >= 0) + DragEnded(); } private void selectionRequested(PathControlPointPiece piece, MouseButtonEvent e) @@ -392,7 +395,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private Vector2[] dragStartPositions; private PathType?[] dragPathTypes; - private int draggedControlPointIndex; + private int draggedControlPointIndex = -1; private HashSet selectedControlPoints; private List curveTypeItems; @@ -473,7 +476,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components EnsureValidPathTypes(); } - public void DragEnded() => changeHandler?.EndChange(); + public void DragEnded() + { + changeHandler?.EndChange(); + draggedControlPointIndex = -1; + } #endregion From 232301f27d35b2de96eabfab0f74ed1902694978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 15 Oct 2024 12:54:08 +0200 Subject: [PATCH 06/15] Terminate existing anchor create operation when object is deselected --- .../Sliders/SliderSelectionBlueprint.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index c72f547565..34de81f1ba 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -178,6 +178,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { base.OnDeselected(); + if (placementControlPoint != null) + endControlPointPlacement(); + updateVisualDefinition(); BodyPiece.RecyclePath(); } @@ -377,13 +380,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override void OnMouseUp(MouseUpEvent e) { if (placementControlPoint != null) - { - if (IsDragged) - ControlPointVisualiser?.DragEnded(); + endControlPointPlacement(); + } - placementControlPoint = null; - changeHandler?.EndChange(); - } + private void endControlPointPlacement() + { + if (IsDragged) + ControlPointVisualiser?.DragEnded(); + + placementControlPoint = null; + changeHandler?.EndChange(); } protected override bool OnKeyDown(KeyDownEvent e) From c5e406a007651762df9aba228f7e857bb4b9a528 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 16 Oct 2024 21:18:48 +0200 Subject: [PATCH 07/15] add keyboard step matching osu stable --- osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs | 1 + osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs b/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs index 352debf500..a87f0286cf 100644 --- a/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs +++ b/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs @@ -55,6 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit MaxValue = 360, Precision = 1 }, + KeyboardStep = 1f, Instantaneous = true }, rotationOrigin = new EditorRadioButtonCollection diff --git a/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs b/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs index b2c48ae326..eafee9db14 100644 --- a/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs +++ b/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs @@ -70,6 +70,7 @@ namespace osu.Game.Rulesets.Osu.Edit Value = 1, Default = 1, }, + KeyboardStep = 0.01f, Instantaneous = true }, scaleOrigin = new EditorRadioButtonCollection From 66bf6ed6b4d10ed497dbd0abb2bdf0552b2abd74 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 16 Oct 2024 21:53:56 +0200 Subject: [PATCH 08/15] Close scale/rotate popover on Enter keypress This matches the expectation from stable where the popover also closes when you press enter. The side-effect is that spacebar also causes it to close, but luckily you don't need spacebar in the popover. --- .../Edit/PreciseRotationPopover.cs | 14 ++++++++++++++ osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs b/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs index a87f0286cf..b18452768c 100644 --- a/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs +++ b/osu.Game.Rulesets.Osu/Edit/PreciseRotationPopover.cs @@ -5,10 +5,13 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Input.Bindings; using osu.Game.Rulesets.Osu.UI; using osu.Game.Screens.Edit.Components.RadioButtons; using osu.Game.Screens.Edit.Compose.Components; @@ -127,6 +130,17 @@ namespace osu.Game.Rulesets.Osu.Edit if (IsLoaded) rotationHandler.Commit(); } + + public override bool OnPressed(KeyBindingPressEvent e) + { + if (e.Action == GlobalAction.Select && !e.Repeat) + { + this.HidePopover(); + return true; + } + + return base.OnPressed(e); + } } public enum RotationOrigin diff --git a/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs b/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs index eafee9db14..68f5b268f8 100644 --- a/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs +++ b/osu.Game.Rulesets.Osu/Edit/PreciseScalePopover.cs @@ -5,11 +5,14 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; @@ -283,6 +286,17 @@ namespace osu.Game.Rulesets.Osu.Edit if (IsLoaded) scaleHandler.Commit(); } + + public override bool OnPressed(KeyBindingPressEvent e) + { + if (e.Action == GlobalAction.Select && !e.Repeat) + { + this.HidePopover(); + return true; + } + + return base.OnPressed(e); + } } public enum ScaleOrigin From e89a4561ab85aa2c1753f24d0526f7ae19e773bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 21 Oct 2024 13:40:35 +0200 Subject: [PATCH 09/15] Fix playfield skinning layer no longer correctly rotating with the playfield Closes https://github.com/ppy/osu/issues/30353. Regressed in https://github.com/ppy/osu/commit/4a39873e2aac3a6fa71a3be06407d9afb7df8922. --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 18 +++++++++++------- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index a28b2716cb..3ad173893b 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -65,18 +65,16 @@ namespace osu.Game.Rulesets.UI /// public override Playfield Playfield => playfield.Value; + private PlayfieldAdjustmentContainer playfieldAdjustmentContainer; + + public override PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer => playfieldAdjustmentContainer; + public override Container Overlays { get; } = new Container { RelativeSizeAxes = Axes.Both }; public override IAdjustableAudioComponent Audio => audioContainer; private readonly AudioContainer audioContainer = new AudioContainer { RelativeSizeAxes = Axes.Both }; - /// - /// A container which encapsulates the and provides any adjustments to - /// ensure correct scale and position. - /// - public virtual PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer { get; private set; } - public override Container FrameStableComponents { get; } = new Container { RelativeSizeAxes = Axes.Both }; public override IFrameStableClock FrameStableClock => frameStabilityContainer; @@ -197,7 +195,7 @@ namespace osu.Game.Rulesets.UI audioContainer.WithChild(KeyBindingInputManager .WithChildren(new Drawable[] { - PlayfieldAdjustmentContainer = CreatePlayfieldAdjustmentContainer() + playfieldAdjustmentContainer = CreatePlayfieldAdjustmentContainer() .WithChild(Playfield), Overlays })), @@ -456,6 +454,12 @@ namespace osu.Game.Rulesets.UI /// public abstract Playfield Playfield { get; } + /// + /// A container which encapsulates the and provides any adjustments to + /// ensure correct scale and position. + /// + public abstract PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer { get; } + /// /// Content to be placed above hitobjects. Will be affected by frame stability and adjustments applied to . /// diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index ac1b9ce34f..292f554483 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -252,7 +252,7 @@ namespace osu.Game.Screens.Play PlayfieldSkinLayer.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); PlayfieldSkinLayer.Width = (ToLocalSpace(playfieldScreenSpaceDrawQuad.TopRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length; PlayfieldSkinLayer.Height = (ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomLeft) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length; - PlayfieldSkinLayer.Rotation = drawableRuleset.Playfield.Rotation; + PlayfieldSkinLayer.Rotation = drawableRuleset.PlayfieldAdjustmentContainer.Rotation; } float? lowestTopScreenSpaceLeft = null; From 1e03bd11a350e4d4af98eb5c12b1c3a1ad412e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 21 Oct 2024 13:57:34 +0200 Subject: [PATCH 10/15] Fix test compile failures --- osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs | 1 + osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs index d4b69c1be2..07d6d68e82 100644 --- a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs +++ b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs @@ -96,6 +96,7 @@ namespace osu.Game.Tests.NonVisual public override IAdjustableAudioComponent Audio { get; } public override Playfield Playfield { get; } + public override PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer { get; } public override Container Overlays { get; } public override Container FrameStableComponents { get; } public override IFrameStableClock FrameStableClock { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index e57177498d..2e646f2850 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -284,6 +284,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override IAdjustableAudioComponent Audio { get; } public override Playfield Playfield { get; } + public override PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer { get; } public override Container Overlays { get; } public override Container FrameStableComponents { get; } public override IFrameStableClock FrameStableClock { get; } From 1008d32ddb61266989877461096ae3a0b13e7d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Oct 2024 14:30:29 +0200 Subject: [PATCH 11/15] Fix old looping samples not stopping when replacing a `SkinnableSound`'s `Samples` Closes https://github.com/ppy/osu/issues/30365. --- osu.Game/Skinning/SkinnableSound.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index f153f4f8d3..be9212da9e 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -154,6 +154,9 @@ namespace osu.Game.Skinning { bool wasPlaying = IsPlaying; + if (wasPlaying && Looping) + Stop(); + // Remove all pooled samples (return them to the pool), and dispose the rest. samplesContainer.RemoveAll(s => s.IsInPool, false); samplesContainer.Clear(); From 21351b1be45d700abf216b7eca14f5bf58aec16f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2024 15:41:42 +0900 Subject: [PATCH 12/15] Quote source text when searching for it via click Addresses https://github.com/ppy/osu/discussions/30181. --- osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs index 544dc0dfe4..c8d4ef5355 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs @@ -17,9 +17,9 @@ namespace osu.Game.Overlays.BeatmapSet protected override void AddMetadata(string metadata, LinkFlowContainer loaded) { if (SearchAction != null) - loaded.AddLink(metadata, () => SearchAction(metadata)); + loaded.AddLink(metadata, () => SearchAction($"\"{metadata}\"")); else - loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, metadata); + loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, $"\"{metadata}\""); } } } From af7d35bfbf50bd3b5891ec1e5e6a1c508e7c2d77 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 23 Oct 2024 16:15:40 +0900 Subject: [PATCH 13/15] Doubly quote strings Note the external-action case (currently used for tags) doesn't match osu!web but it doesn't matter because tags are single words anyway. --- osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs index c8d4ef5355..92511df498 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs @@ -17,9 +17,9 @@ namespace osu.Game.Overlays.BeatmapSet protected override void AddMetadata(string metadata, LinkFlowContainer loaded) { if (SearchAction != null) - loaded.AddLink(metadata, () => SearchAction($"\"{metadata}\"")); + loaded.AddLink(metadata, () => SearchAction($@"""""{metadata}""""")); else - loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, $"\"{metadata}\""); + loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, $@"""""{metadata}"""""); } } } From 2bea1fe4a6cfbcc313e12dabb98c314164ae5b4d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 23 Oct 2024 16:21:28 +0900 Subject: [PATCH 14/15] Also add source prefix --- osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs index 92511df498..4d55359e63 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs @@ -17,9 +17,9 @@ namespace osu.Game.Overlays.BeatmapSet protected override void AddMetadata(string metadata, LinkFlowContainer loaded) { if (SearchAction != null) - loaded.AddLink(metadata, () => SearchAction($@"""""{metadata}""""")); + loaded.AddLink(metadata, () => SearchAction($@"source=""""{metadata}""""")); else - loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, $@"""""{metadata}"""""); + loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, $@"source=""""{metadata}"""""); } } } From 064aaeb60e07e51d80582c2ecde491008166d1fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2024 18:46:20 +0900 Subject: [PATCH 15/15] Initialise container earlier to avoid null reference failures --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 3ad173893b..ebd84fd91b 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -65,8 +65,6 @@ namespace osu.Game.Rulesets.UI /// public override Playfield Playfield => playfield.Value; - private PlayfieldAdjustmentContainer playfieldAdjustmentContainer; - public override PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer => playfieldAdjustmentContainer; public override Container Overlays { get; } = new Container { RelativeSizeAxes = Axes.Both }; @@ -79,6 +77,8 @@ namespace osu.Game.Rulesets.UI public override IFrameStableClock FrameStableClock => frameStabilityContainer; + private readonly PlayfieldAdjustmentContainer playfieldAdjustmentContainer; + private bool allowBackwardsSeeks; public override bool AllowBackwardsSeeks @@ -144,6 +144,7 @@ namespace osu.Game.Rulesets.UI RelativeSizeAxes = Axes.Both; KeyBindingInputManager = CreateInputManager(); + playfieldAdjustmentContainer = CreatePlayfieldAdjustmentContainer(); playfield = new Lazy(() => CreatePlayfield().With(p => { p.NewResult += (_, r) => NewResult?.Invoke(r); @@ -195,8 +196,7 @@ namespace osu.Game.Rulesets.UI audioContainer.WithChild(KeyBindingInputManager .WithChildren(new Drawable[] { - playfieldAdjustmentContainer = CreatePlayfieldAdjustmentContainer() - .WithChild(Playfield), + playfieldAdjustmentContainer.WithChild(Playfield), Overlays })), }