mirror of
https://github.com/ppy/osu.git
synced 2024-11-07 20:07:24 +08:00
Merge pull request #6818 from smoogipoo/slider-controlpoint-addition
Implement slider control point additions
This commit is contained in:
commit
574de39b0d
@ -1,8 +1,14 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -10,6 +16,7 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
{
|
||||
@ -44,6 +51,78 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
BodyPiece.UpdateFrom(HitObject);
|
||||
}
|
||||
|
||||
private Vector2 rightClickPosition;
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
switch (e.Button)
|
||||
{
|
||||
case MouseButton.Right:
|
||||
rightClickPosition = e.MouseDownPosition;
|
||||
return false; // Allow right click to be handled by context menu
|
||||
|
||||
case MouseButton.Left when e.ControlPressed && IsSelected:
|
||||
placementControlPointIndex = addControlPoint(e.MousePosition);
|
||||
return true; // Stop input from being handled and modifying the selection
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int? placementControlPointIndex;
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e) => placementControlPointIndex != null;
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
{
|
||||
Debug.Assert(placementControlPointIndex != null);
|
||||
|
||||
Vector2 position = e.MousePosition - HitObject.Position;
|
||||
|
||||
var controlPoints = HitObject.Path.ControlPoints.ToArray();
|
||||
controlPoints[placementControlPointIndex.Value] = position;
|
||||
|
||||
onNewControlPoints(controlPoints);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(DragEndEvent e)
|
||||
{
|
||||
placementControlPointIndex = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private int addControlPoint(Vector2 position)
|
||||
{
|
||||
position -= HitObject.Position;
|
||||
|
||||
var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1];
|
||||
HitObject.Path.ControlPoints.CopyTo(controlPoints);
|
||||
|
||||
int insertionIndex = 0;
|
||||
float minDistance = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < controlPoints.Length - 2; i++)
|
||||
{
|
||||
float dist = new Line(controlPoints[i], controlPoints[i + 1]).DistanceToPoint(position);
|
||||
|
||||
if (dist < minDistance)
|
||||
{
|
||||
insertionIndex = i + 1;
|
||||
minDistance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
// Move the control points from the insertion index onwards to make room for the insertion
|
||||
Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1);
|
||||
controlPoints[insertionIndex] = position;
|
||||
|
||||
onNewControlPoints(controlPoints);
|
||||
|
||||
return insertionIndex;
|
||||
}
|
||||
|
||||
private void onNewControlPoints(Vector2[] controlPoints)
|
||||
{
|
||||
var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints);
|
||||
@ -54,6 +133,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
UpdateHitObject();
|
||||
}
|
||||
|
||||
public override MenuItem[] ContextMenuItems => new MenuItem[]
|
||||
{
|
||||
new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)),
|
||||
};
|
||||
|
||||
public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -104,6 +105,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MenuItem"/>s to be displayed in the context menu for this <see cref="SelectionBlueprint"/>.
|
||||
/// </summary>
|
||||
public virtual MenuItem[] ContextMenuItems => Array.Empty<MenuItem>();
|
||||
|
||||
/// <summary>
|
||||
/// The screen-space point that causes this <see cref="SelectionBlueprint"/> to be selected.
|
||||
/// </summary>
|
||||
|
@ -229,7 +229,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
if (!selectedBlueprints.Any(b => b.IsHovered))
|
||||
return Array.Empty<MenuItem>();
|
||||
|
||||
return new MenuItem[]
|
||||
var items = new List<MenuItem>
|
||||
{
|
||||
new OsuMenuItem("Sound")
|
||||
{
|
||||
@ -242,6 +242,11 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
},
|
||||
new OsuMenuItem("Delete", MenuItemType.Destructive, deleteSelected),
|
||||
};
|
||||
|
||||
if (selectedBlueprints.Count == 1)
|
||||
items.AddRange(selectedBlueprints[0].ContextMenuItems);
|
||||
|
||||
return items.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user