mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 08:49:59 +09:00
Add the ability to delete slider control points using shift+right click
Closes https://github.com/ppy/osu/issues/10672. In two minds about how this should be implemented but went in this direction initially. The other way would be to add local handling of Shift-Right Click inside PathControlPointPiece (which is already doing mouse handling itself).
This commit is contained in:
@ -18,6 +18,7 @@ using osu.Game.Graphics.UserInterface;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||||
@ -105,7 +106,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
switch (action.ActionMethod)
|
switch (action.ActionMethod)
|
||||||
{
|
{
|
||||||
case PlatformActionMethod.Delete:
|
case PlatformActionMethod.Delete:
|
||||||
return deleteSelected();
|
return DeleteSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -115,6 +116,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
|
Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos));
|
||||||
|
|
||||||
private void selectPiece(PathControlPointPiece piece, MouseButtonEvent e)
|
private void selectPiece(PathControlPointPiece piece, MouseButtonEvent e)
|
||||||
{
|
{
|
||||||
if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed)
|
if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed)
|
||||||
@ -126,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool deleteSelected()
|
public bool DeleteSelected()
|
||||||
{
|
{
|
||||||
List<PathControlPoint> toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => p.ControlPoint).ToList();
|
List<PathControlPoint> toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => p.ControlPoint).ToList();
|
||||||
|
|
||||||
@ -169,7 +173,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
|
|
||||||
return new MenuItem[]
|
return new MenuItem[]
|
||||||
{
|
{
|
||||||
new OsuMenuItem($"Delete {"control point".ToQuantity(count, count > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => deleteSelected()),
|
new OsuMenuItem($"Delete {"control point".ToQuantity(count, count > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => DeleteSelected()),
|
||||||
new OsuMenuItem("Curve type")
|
new OsuMenuItem("Curve type")
|
||||||
{
|
{
|
||||||
Items = items
|
Items = items
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -72,6 +73,18 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
BodyPiece.UpdateFrom(HitObject);
|
BodyPiece.UpdateFrom(HitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool HandleQuickDeletion()
|
||||||
|
{
|
||||||
|
var hoveredControlPoint = ControlPointVisualiser.Pieces.FirstOrDefault(p => p.IsHovered);
|
||||||
|
|
||||||
|
if (hoveredControlPoint == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hoveredControlPoint.IsSelected.Value = true;
|
||||||
|
ControlPointVisualiser.DeleteSelected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -216,7 +229,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
|
|
||||||
public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation);
|
public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation);
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos);
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
|
BodyPiece.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.ReceivePositionalInputAt(screenSpacePos) == true;
|
||||||
|
|
||||||
protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position);
|
protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position);
|
||||||
}
|
}
|
||||||
|
@ -143,5 +143,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
public virtual Quad SelectionQuad => ScreenSpaceDrawQuad;
|
public virtual Quad SelectionQuad => ScreenSpaceDrawQuad;
|
||||||
|
|
||||||
public virtual Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Parent.ToLocalSpace(screenSpacePosition) - Position;
|
public virtual Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Parent.ToLocalSpace(screenSpacePosition) - Position;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle to perform a partial deletion when the user requests a quick delete (Shift+Right Click).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the deletion operation was handled by this blueprint. Returning false will delete the full blueprint.</returns>
|
||||||
|
public virtual bool HandleQuickDeletion() => false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
beginClickSelection(e);
|
if (beginClickSelection(e)) return true;
|
||||||
|
|
||||||
prepareSelectionMovement();
|
prepareSelectionMovement();
|
||||||
|
|
||||||
return e.Button == MouseButton.Left;
|
return e.Button == MouseButton.Left;
|
||||||
@ -291,19 +292,23 @@ 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(MouseButtonEvent e)
|
private bool beginClickSelection(MouseButtonEvent e)
|
||||||
{
|
{
|
||||||
Debug.Assert(!clickSelectionBegan);
|
Debug.Assert(!clickSelectionBegan);
|
||||||
|
|
||||||
|
bool rightClickHandled = false;
|
||||||
|
|
||||||
foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren)
|
foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren)
|
||||||
{
|
{
|
||||||
if (blueprint.IsHovered)
|
if (blueprint.IsHovered)
|
||||||
{
|
{
|
||||||
SelectionHandler.HandleSelectionRequested(blueprint, e.CurrentState);
|
rightClickHandled |= SelectionHandler.HandleSelectionRequested(blueprint, e.CurrentState);
|
||||||
clickSelectionBegan = true;
|
clickSelectionBegan = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return rightClickHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -219,18 +219,28 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="blueprint">The blueprint.</param>
|
/// <param name="blueprint">The blueprint.</param>
|
||||||
/// <param name="state">The input state at the point of selection.</param>
|
/// <param name="state">The input state at the point of selection.</param>
|
||||||
internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
|
/// <returns>Whether right click was handled.</returns>
|
||||||
|
internal bool HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
|
||||||
{
|
{
|
||||||
if (state.Keyboard.ShiftPressed && state.Mouse.IsPressed(MouseButton.Right))
|
if (state.Keyboard.ShiftPressed && state.Mouse.IsPressed(MouseButton.Right))
|
||||||
|
{
|
||||||
handleQuickDeletion(blueprint);
|
handleQuickDeletion(blueprint);
|
||||||
else if (state.Keyboard.ControlPressed && state.Mouse.IsPressed(MouseButton.Left))
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.Keyboard.ControlPressed && state.Mouse.IsPressed(MouseButton.Left))
|
||||||
blueprint.ToggleSelection();
|
blueprint.ToggleSelection();
|
||||||
else
|
else
|
||||||
ensureSelected(blueprint);
|
ensureSelected(blueprint);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleQuickDeletion(SelectionBlueprint blueprint)
|
private void handleQuickDeletion(SelectionBlueprint blueprint)
|
||||||
{
|
{
|
||||||
|
if (blueprint.HandleQuickDeletion())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!blueprint.IsSelected)
|
if (!blueprint.IsSelected)
|
||||||
EditorBeatmap.Remove(blueprint.HitObject);
|
EditorBeatmap.Remove(blueprint.HitObject);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user