diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs new file mode 100644 index 0000000000..bbae10e5ff --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -0,0 +1,123 @@ +// 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 Humanizer; +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osu.Game.Screens.Edit.Timing; +using osu.Game.Tests.Beatmaps; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Editing +{ + public class TestSceneHitObjectDifficultyPointAdjustments : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("add test objects", () => + { + EditorBeatmap.Add(new Slider + { + StartTime = 0, + Position = (OsuPlayfield.BASE_SIZE - new Vector2(0, 100)) / 2, + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(new Vector2(0, 0)), + new PathControlPoint(new Vector2(0, 100)) + } + } + }); + + EditorBeatmap.Add(new Slider + { + StartTime = 500, + Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2, + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(new Vector2(0, 0)), + new PathControlPoint(new Vector2(100, 0)) + } + }, + DifficultyControlPoint = new DifficultyControlPoint + { + SliderVelocity = 2 + } + }); + }); + } + + [Test] + public void TestSingleSelection() + { + clickDifficultyPiece(0); + velocityPopoverHasSingleValue(1); + + dismissPopover(); + + // select first object to ensure that difficulty pieces for unselected objects + // work independently from selection state. + AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First())); + + clickDifficultyPiece(1); + velocityPopoverHasSingleValue(2); + + setVelocityViaPopover(5); + hitObjectHasVelocity(1, 5); + } + + private void clickDifficultyPiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} difficulty piece", () => + { + var difficultyPiece = this.ChildrenOfType().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex)); + + InputManager.MoveMouseTo(difficultyPiece); + InputManager.Click(MouseButton.Left); + }); + + private void velocityPopoverHasSingleValue(double velocity) => AddUntilStep($"velocity popover has {velocity}", () => + { + var popover = this.ChildrenOfType().SingleOrDefault(); + var slider = popover?.ChildrenOfType>().Single(); + + return slider?.Current.Value == velocity; + }); + + private void dismissPopover() + { + AddStep("dismiss popover", () => InputManager.Key(Key.Escape)); + AddUntilStep("wait for dismiss", () => !this.ChildrenOfType().Any(popover => popover.IsPresent)); + } + + private void setVelocityViaPopover(double velocity) => AddStep($"set {velocity} via popover", () => + { + var popover = this.ChildrenOfType().Single(); + var slider = popover.ChildrenOfType>().Single(); + slider.Current.Value = velocity; + }); + + private void hitObjectHasVelocity(int objectIndex, double velocity) => AddAssert($"{objectIndex.ToOrdinalWords()} has velocity {velocity}", () => + { + var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); + return h.DifficultyControlPoint.SliderVelocity == velocity; + }); + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 21457ea273..ae1884d295 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -19,14 +19,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public class DifficultyPointPiece : HitObjectPointPiece, IHasPopover { - private readonly HitObject hitObject; + public readonly HitObject HitObject; private readonly BindableNumber speedMultiplier; public DifficultyPointPiece(HitObject hitObject) : base(hitObject.DifficultyControlPoint) { - this.hitObject = hitObject; + HitObject = hitObject; speedMultiplier = hitObject.DifficultyControlPoint.SliderVelocityBindable.GetBoundCopy(); } @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return true; } - public Popover GetPopover() => new DifficultyEditPopover(hitObject); + public Popover GetPopover() => new DifficultyEditPopover(HitObject); public class DifficultyEditPopover : OsuPopover {