mirror of
https://github.com/ppy/osu.git
synced 2026-05-18 18:29:58 +08:00
Add slider control point deletion right-click menu item (#6832)
Add slider control point deletion right-click menu item Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
@@ -14,12 +14,13 @@ using osu.Game.Rulesets.Edit;
|
|||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||||
{
|
{
|
||||||
public class PathControlPointPiece : BlueprintPiece<Slider>
|
public class PathControlPointPiece : BlueprintPiece<Slider>
|
||||||
{
|
{
|
||||||
public Action<int> RequestSelection;
|
public Action<int, MouseButtonEvent> RequestSelection;
|
||||||
public Action<Vector2[]> ControlPointsChanged;
|
public Action<Vector2[]> ControlPointsChanged;
|
||||||
|
|
||||||
public readonly BindableBool IsSelected = new BindableBool();
|
public readonly BindableBool IsSelected = new BindableBool();
|
||||||
@@ -129,10 +130,19 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
if (RequestSelection != null)
|
if (RequestSelection == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (e.Button)
|
||||||
{
|
{
|
||||||
RequestSelection.Invoke(Index);
|
case MouseButton.Left:
|
||||||
return true;
|
RequestSelection.Invoke(Index, e);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MouseButton.Right:
|
||||||
|
if (!IsSelected.Value)
|
||||||
|
RequestSelection.Invoke(Index, e);
|
||||||
|
return false; // Allow context menu to show
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -142,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
|
|
||||||
protected override bool OnClick(ClickEvent e) => RequestSelection != null;
|
protected override bool OnClick(ClickEvent e) => RequestSelection != null;
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e) => true;
|
protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left;
|
||||||
|
|
||||||
protected override bool OnDrag(DragEvent e)
|
protected override bool OnDrag(DragEvent e)
|
||||||
{
|
{
|
||||||
|
|||||||
+71
-42
@@ -3,19 +3,25 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Humanizer;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Edit.Compose;
|
using osu.Game.Screens.Edit.Compose;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||||
{
|
{
|
||||||
public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler<PlatformAction>
|
public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler<PlatformAction>, IHasContextMenu
|
||||||
{
|
{
|
||||||
public Action<Vector2[]> ControlPointsChanged;
|
public Action<Vector2[]> ControlPointsChanged;
|
||||||
|
|
||||||
@@ -73,9 +79,22 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectPiece(int index)
|
public bool OnPressed(PlatformAction action)
|
||||||
{
|
{
|
||||||
if (inputManager.CurrentState.Keyboard.ControlPressed)
|
switch (action.ActionMethod)
|
||||||
|
{
|
||||||
|
case PlatformActionMethod.Delete:
|
||||||
|
return deleteSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete;
|
||||||
|
|
||||||
|
private void selectPiece(int index, MouseButtonEvent e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed)
|
||||||
Pieces[index].IsSelected.Toggle();
|
Pieces[index].IsSelected.Toggle();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -84,50 +103,60 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(PlatformAction action)
|
private bool deleteSelected()
|
||||||
{
|
{
|
||||||
switch (action.ActionMethod)
|
var newControlPoints = new List<Vector2>();
|
||||||
|
|
||||||
|
foreach (var piece in Pieces)
|
||||||
{
|
{
|
||||||
case PlatformActionMethod.Delete:
|
if (!piece.IsSelected.Value)
|
||||||
var newControlPoints = new List<Vector2>();
|
newControlPoints.Add(slider.Path.ControlPoints[piece.Index]);
|
||||||
|
|
||||||
foreach (var piece in Pieces)
|
|
||||||
{
|
|
||||||
if (!piece.IsSelected.Value)
|
|
||||||
newControlPoints.Add(slider.Path.ControlPoints[piece.Index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that there are any points to be deleted
|
|
||||||
if (newControlPoints.Count == slider.Path.ControlPoints.Length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If there are 0 remaining control points, treat the slider as being deleted
|
|
||||||
if (newControlPoints.Count == 0)
|
|
||||||
{
|
|
||||||
placementHandler?.Delete(slider);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make control points relative
|
|
||||||
Vector2 first = newControlPoints[0];
|
|
||||||
for (int i = 0; i < newControlPoints.Count; i++)
|
|
||||||
newControlPoints[i] = newControlPoints[i] - first;
|
|
||||||
|
|
||||||
// The slider's position defines the position of the first control point, and all further control points are relative to that point
|
|
||||||
slider.Position = slider.Position + first;
|
|
||||||
|
|
||||||
// Since pieces are re-used, they will not point to the deleted control points while remaining selected
|
|
||||||
foreach (var piece in Pieces)
|
|
||||||
piece.IsSelected.Value = false;
|
|
||||||
|
|
||||||
ControlPointsChanged?.Invoke(newControlPoints.ToArray());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Ensure that there are any points to be deleted
|
||||||
|
if (newControlPoints.Count == slider.Path.ControlPoints.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If there are 0 remaining control points, treat the slider as being deleted
|
||||||
|
if (newControlPoints.Count == 0)
|
||||||
|
{
|
||||||
|
placementHandler?.Delete(slider);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make control points relative
|
||||||
|
Vector2 first = newControlPoints[0];
|
||||||
|
for (int i = 0; i < newControlPoints.Count; i++)
|
||||||
|
newControlPoints[i] = newControlPoints[i] - first;
|
||||||
|
|
||||||
|
// The slider's position defines the position of the first control point, and all further control points are relative to that point
|
||||||
|
slider.Position = slider.Position + first;
|
||||||
|
|
||||||
|
// Since pieces are re-used, they will not point to the deleted control points while remaining selected
|
||||||
|
foreach (var piece in Pieces)
|
||||||
|
piece.IsSelected.Value = false;
|
||||||
|
|
||||||
|
ControlPointsChanged?.Invoke(newControlPoints.ToArray());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete;
|
public MenuItem[] ContextMenuItems
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!Pieces.Any(p => p.IsHovered))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int selectedPoints = Pieces.Count(p => p.IsSelected.Value);
|
||||||
|
|
||||||
|
if (selectedPoints == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new MenuItem[]
|
||||||
|
{
|
||||||
|
new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,14 +313,15 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
/// Attempts to select any hovered blueprints.
|
/// Attempts to select any hovered blueprints.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">The input event that triggered this selection.</param>
|
/// <param name="e">The input event that triggered this selection.</param>
|
||||||
private void beginClickSelection(UIEvent e)
|
private void beginClickSelection(MouseButtonEvent e)
|
||||||
{
|
{
|
||||||
Debug.Assert(!clickSelectionBegan);
|
Debug.Assert(!clickSelectionBegan);
|
||||||
|
|
||||||
// If a select blueprint is already hovered, disallow changes in selection.
|
// Deselections are only allowed for control + left clicks
|
||||||
// Exception is made when holding control, as deselection should still be allowed.
|
bool allowDeselection = e.ControlPressed && e.Button == MouseButton.Left;
|
||||||
if (!e.CurrentState.Keyboard.ControlPressed &&
|
|
||||||
selectionHandler.SelectedBlueprints.Any(s => s.IsHovered))
|
// Todo: This is probably incorrectly disallowing multiple selections on stacked objects
|
||||||
|
if (!allowDeselection && selectionHandler.SelectedBlueprints.Any(s => s.IsHovered))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints)
|
foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints)
|
||||||
|
|||||||
Reference in New Issue
Block a user