From 7a3ebcd0b1c77b7caaac8c88f0a722353acd4a25 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 15:52:38 +0900 Subject: [PATCH 1/6] Fix path changes not updating tail circle --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 010bf072e8..f60b7e67b2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Osu.Objects { PathBindable.Value = value; endPositionCache.Invalidate(); + + updateNestedPositions(); } } @@ -48,14 +50,9 @@ namespace osu.Game.Rulesets.Osu.Objects set { base.Position = value; - endPositionCache.Invalidate(); - if (HeadCircle != null) - HeadCircle.Position = value; - - if (TailCircle != null) - TailCircle.Position = EndPosition; + updateNestedPositions(); } } @@ -197,6 +194,15 @@ namespace osu.Game.Rulesets.Osu.Objects } } + private void updateNestedPositions() + { + if (HeadCircle != null) + HeadCircle.Position = Position; + + if (TailCircle != null) + TailCircle.Position = EndPosition; + } + private List getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; From e23a75c64a400705b202122570ca1f41d09c0735 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:23:54 +0900 Subject: [PATCH 2/6] Implement control point selection --- .../Components/PathControlPointPiece.cs | 84 +++++++++++++++---- .../Components/PathControlPointVisualiser.cs | 21 +++++ 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 7afb8fcf49..3b0b9bce1f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; @@ -11,18 +12,21 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { public Action ControlPointsChanged; + public readonly Bindable IsSelected = new Bindable(); + + public readonly int Index; private readonly Slider slider; - private readonly int index; - private readonly Path path; - private readonly CircularContainer marker; + private readonly Container marker; + private readonly Drawable markerRing; [Resolved] private OsuColour colours { get; set; } @@ -30,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public PathControlPointPiece(Slider slider, int index) { this.slider = slider; - this.index = index; + Index = index; Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; @@ -42,13 +46,36 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components Anchor = Anchor.Centre, PathRadius = 1 }, - marker = new CircularContainer + marker = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(10), - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } + AutoSizeAxes = Axes.Both, + Children = new[] + { + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(10), + }, + markerRing = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(14), + Masking = true, + BorderThickness = 2, + BorderColour = Color4.White, + Alpha = 0, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + } } }; } @@ -57,21 +84,42 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { base.Update(); - Position = slider.StackedPosition + slider.Path.ControlPoints[index]; + Position = slider.StackedPosition + slider.Path.ControlPoints[Index]; - marker.Colour = isSegmentSeparator ? colours.Red : colours.Yellow; + updateMarkerDisplay(); + updateConnectingPath(); + } + /// + /// Updates the state of the circular control point marker. + /// + private void updateMarkerDisplay() + { + markerRing.Alpha = IsSelected.Value ? 1 : 0; + + Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; + if (IsHovered || IsSelected.Value) + colour = Color4.White; + marker.Colour = colour; + } + + /// + /// Updates the path connecting this control point to the previous one. + /// + private void updateConnectingPath() + { path.ClearVertices(); - if (index != slider.Path.ControlPoints.Length - 1) + if (Index != slider.Path.ControlPoints.Length - 1) { path.AddVertex(Vector2.Zero); - path.AddVertex(slider.Path.ControlPoints[index + 1] - slider.Path.ControlPoints[index]); + path.AddVertex(slider.Path.ControlPoints[Index + 1] - slider.Path.ControlPoints[Index]); } path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); } + // The connecting path is excluded from positional input public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); protected override bool OnDragStart(DragStartEvent e) => true; @@ -80,7 +128,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { var newControlPoints = slider.Path.ControlPoints.ToArray(); - if (index == 0) + if (Index == 0) { // Special handling for the head - only the position of the slider changes slider.Position += e.Delta; @@ -90,13 +138,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components newControlPoints[i] -= e.Delta; } else - newControlPoints[index] += e.Delta; + newControlPoints[Index] += e.Delta; if (isSegmentSeparatorWithNext) - newControlPoints[index + 1] = newControlPoints[index]; + newControlPoints[Index + 1] = newControlPoints[Index]; if (isSegmentSeparatorWithPrevious) - newControlPoints[index - 1] = newControlPoints[index]; + newControlPoints[Index - 1] = newControlPoints[Index]; ControlPointsChanged?.Invoke(newControlPoints); @@ -107,8 +155,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private bool isSegmentSeparator => isSegmentSeparatorWithNext || isSegmentSeparatorWithPrevious; - private bool isSegmentSeparatorWithNext => index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[index + 1] == slider.Path.ControlPoints[index]; + private bool isSegmentSeparatorWithNext => Index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[Index + 1] == slider.Path.ControlPoints[Index]; - private bool isSegmentSeparatorWithPrevious => index > 0 && slider.Path.ControlPoints[index - 1] == slider.Path.ControlPoints[index]; + private bool isSegmentSeparatorWithPrevious => Index > 0 && slider.Path.ControlPoints[Index - 1] == slider.Path.ControlPoints[Index]; } } 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 0385824b27..b0e579907d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { this.slider = slider; + RelativeSizeAxes = Axes.Both; + InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both }; } @@ -33,5 +36,23 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components while (slider.Path.ControlPoints.Length < pieces.Count) pieces.Remove(pieces[pieces.Count - 1]); } + + protected override bool OnMouseDown(MouseDownEvent e) + { + bool anySelected = false; + + foreach (var piece in pieces) + { + if (piece.IsHovered) + { + piece.IsSelected.Value = true; + anySelected = true; + } + else + piece.IsSelected.Value = false; + } + + return anySelected; + } } } From cfdf7106764b904c733e001eeba71b1e6b005d97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:51:58 +0900 Subject: [PATCH 3/6] Add test --- .../TestSceneSliderSelectionBlueprint.cs | 33 +++++++++++++++++++ .../Components/PathControlPointVisualiser.cs | 16 ++++----- .../Sliders/SliderSelectionBlueprint.cs | 3 +- .../Visual/SelectionBlueprintTestScene.cs | 2 +- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 5df0b70f12..0e7d8c9c08 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Tests.Visual; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests { @@ -85,6 +86,25 @@ namespace osu.Game.Rulesets.Osu.Tests checkPositions(); } + [Test] + public void TestSingleControlPointSelection() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, true); + checkControlPointSelected(1, false); + + moveMouseToControlPoint(1); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, true); + + AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + private void moveHitObject() { AddStep("move hitobject", () => @@ -104,11 +124,24 @@ namespace osu.Game.Rulesets.Osu.Tests () => Precision.AlmostEquals(blueprint.TailBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.TailCircle.ScreenSpaceDrawQuad.Centre)); } + private void moveMouseToControlPoint(int index) + { + AddStep($"move mouse to control point {index}", () => + { + Vector2 position = slider.Position + slider.Path.ControlPoints[index]; + InputManager.MoveMouseTo(drawableObject.Parent.ToScreenSpace(position)); + }); + } + + private void checkControlPointSelected(int index, bool selected) + => AddAssert($"control point {index} {(selected ? "selected" : "not selected")}", () => blueprint.ControlPointVisualiser.Pieces[index].IsSelected.Value == selected); + private class TestSliderBlueprint : SliderSelectionBlueprint { public new SliderBodyPiece BodyPiece => base.BodyPiece; public new TestSliderCircleBlueprint HeadBlueprint => (TestSliderCircleBlueprint)base.HeadBlueprint; public new TestSliderCircleBlueprint TailBlueprint => (TestSliderCircleBlueprint)base.TailBlueprint; + public new PathControlPointVisualiser ControlPointVisualiser => base.ControlPointVisualiser; public TestSliderBlueprint(DrawableSlider slider) : base(slider) 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 b0e579907d..6efa0ef550 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -14,9 +14,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public Action ControlPointsChanged; - private readonly Slider slider; + internal Container Pieces { get; } - private readonly Container pieces; + private readonly Slider slider; public PathControlPointVisualiser(Slider slider) { @@ -24,24 +24,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components RelativeSizeAxes = Axes.Both; - InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both }; + InternalChild = Pieces = new Container { RelativeSizeAxes = Axes.Both }; } protected override void Update() { base.Update(); - while (slider.Path.ControlPoints.Length > pieces.Count) - pieces.Add(new PathControlPointPiece(slider, pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); - while (slider.Path.ControlPoints.Length < pieces.Count) - pieces.Remove(pieces[pieces.Count - 1]); + while (slider.Path.ControlPoints.Length > Pieces.Count) + Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); + while (slider.Path.ControlPoints.Length < Pieces.Count) + Pieces.Remove(Pieces[Pieces.Count - 1]); } protected override bool OnMouseDown(MouseDownEvent e) { bool anySelected = false; - foreach (var piece in pieces) + foreach (var piece in Pieces) { if (piece.IsHovered) { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index b09f598bcc..ba502d3a7c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; protected readonly SliderCircleSelectionBlueprint TailBlueprint; + protected readonly PathControlPointVisualiser ControlPointVisualiser; [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, + ControlPointVisualiser = new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, }; } diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index f53c12b047..3233ee160d 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Edit; namespace osu.Game.Tests.Visual { - public abstract class SelectionBlueprintTestScene : OsuTestScene + public abstract class SelectionBlueprintTestScene : ManualInputManagerTestScene { protected override Container Content => content ?? base.Content; private readonly Container content; From 8d50b155e8022f43bca1a9c824ee8697aa4acf70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:13:10 +0900 Subject: [PATCH 4/6] Make selection happen on click only --- .../Components/PathControlPointPiece.cs | 25 ++++++++++++++-- .../Components/PathControlPointVisualiser.cs | 30 ++++++++++--------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 3b0b9bce1f..bd6a905b38 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -18,9 +18,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { + public Action RequestSelection; public Action ControlPointsChanged; - public readonly Bindable IsSelected = new Bindable(); + public readonly Bindable IsSelected = new Bindable(); public readonly int Index; private readonly Slider slider; @@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; + private bool isClicked; + [Resolved] private OsuColour colours { get; set; } @@ -98,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components markerRing.Alpha = IsSelected.Value ? 1 : 0; Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; - if (IsHovered || IsSelected.Value) + if (IsHovered || isClicked || IsSelected.Value) colour = Color4.White; marker.Colour = colour; } @@ -122,6 +125,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components // The connecting path is excluded from positional input public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); + protected override bool OnMouseDown(MouseDownEvent e) + { + isClicked = true; + return true; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + isClicked = false; + return true; + } + + protected override bool OnClick(ClickEvent e) + { + RequestSelection?.Invoke(Index); + return true; + } + protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDrag(DragEvent e) 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 6efa0ef550..160168eb37 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -32,27 +32,29 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.Update(); while (slider.Path.ControlPoints.Length > Pieces.Count) - Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); + { + Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) + { + ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), + RequestSelection = selectPiece + }); + } + while (slider.Path.ControlPoints.Length < Pieces.Count) Pieces.Remove(Pieces[Pieces.Count - 1]); } - protected override bool OnMouseDown(MouseDownEvent e) + protected override bool OnClick(ClickEvent e) { - bool anySelected = false; - foreach (var piece in Pieces) - { - if (piece.IsHovered) - { - piece.IsSelected.Value = true; - anySelected = true; - } - else - piece.IsSelected.Value = false; - } + piece.IsSelected.Value = false; + return false; + } - return anySelected; + private void selectPiece(int index) + { + foreach (var piece in Pieces) + piece.IsSelected.Value = piece.Index == index; } } } From 20aeb7aaffe4fe48bfcfa820a49f7765dc544bce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:25:30 +0900 Subject: [PATCH 5/6] Implement multiple selection --- .../TestSceneSliderSelectionBlueprint.cs | 68 +++++++++++++++++++ .../Components/PathControlPointVisualiser.cs | 22 ++++-- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 0e7d8c9c08..dde2aa53e0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -93,11 +93,79 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("click", () => InputManager.Click(MouseButton.Left)); checkControlPointSelected(0, true); checkControlPointSelected(1, false); + } + + [Test] + public void TestSingleControlPointDeselectionViaOtherControlPoint() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); moveMouseToControlPoint(1); AddStep("click", () => InputManager.Click(MouseButton.Left)); checkControlPointSelected(0, false); checkControlPointSelected(1, true); + } + + [Test] + public void TestSingleControlPointDeselectionViaClickOutside() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + + [Test] + public void TestMultipleControlPointSelection() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + checkControlPointSelected(0, true); + checkControlPointSelected(1, true); + } + + [Test] + public void TestMultipleControlPointDeselectionViaOtherControlPoint() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + moveMouseToControlPoint(2); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + + [Test] + public void TestMultipleControlPointDeselectionViaClickOutside() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); AddStep("click", () => InputManager.Click(MouseButton.Left)); 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 160168eb37..bbe771d8b0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -14,10 +15,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public Action ControlPointsChanged; - internal Container Pieces { get; } - + internal readonly Container Pieces; private readonly Slider slider; + private InputManager inputManager; + public PathControlPointVisualiser(Slider slider) { this.slider = slider; @@ -27,6 +29,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChild = Pieces = new Container { RelativeSizeAxes = Axes.Both }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + } + protected override void Update() { base.Update(); @@ -53,8 +62,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private void selectPiece(int index) { - foreach (var piece in Pieces) - piece.IsSelected.Value = piece.Index == index; + if (inputManager.CurrentState.Keyboard.ControlPressed) + Pieces[index].IsSelected.Value = true; + else + { + foreach (var piece in Pieces) + piece.IsSelected.Value = piece.Index == index; + } } } } From 4dbdfcdd3c601a547887b9b563c06692feb6c53f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 18:41:29 +0900 Subject: [PATCH 6/6] Change control to toggle rather than always select --- .../Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs | 2 +- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index bd6a905b38..e2ea6a12d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public Action RequestSelection; public Action ControlPointsChanged; - public readonly Bindable IsSelected = new Bindable(); + public readonly BindableBool IsSelected = new BindableBool(); public readonly int Index; private readonly Slider slider; 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 bbe771d8b0..b70c11427a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private void selectPiece(int index) { if (inputManager.CurrentState.Keyboard.ControlPressed) - Pieces[index].IsSelected.Value = true; + Pieces[index].IsSelected.Toggle(); else { foreach (var piece in Pieces)