1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-17 01:32:55 +08:00

use minimum enclosing circle selection centre in rotation

This commit is contained in:
OliBomby 2024-09-20 01:07:47 +02:00
parent 59ab71f786
commit ee00624751
4 changed files with 21 additions and 13 deletions

View File

@ -47,7 +47,6 @@ namespace osu.Game.Rulesets.Osu.Edit
private OsuHitObject[]? objectsInRotation;
private Vector2? defaultOrigin;
private Dictionary<OsuHitObject, Vector2>? originalPositions;
private Dictionary<IHasPath, Vector2[]>? originalPathControlPointPositions;
@ -61,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Edit
changeHandler?.BeginChange();
objectsInRotation = selectedMovableObjects.ToArray();
defaultOrigin = GeometryUtils.GetSurroundingQuad(objectsInRotation).Centre;
DefaultOrigin = GeometryUtils.MinimumEnclosingCircle(objectsInRotation).Item1;
originalPositions = objectsInRotation.ToDictionary(obj => obj, obj => obj.Position);
originalPathControlPointPositions = objectsInRotation.OfType<IHasPath>().ToDictionary(
obj => obj,
@ -73,9 +72,9 @@ namespace osu.Game.Rulesets.Osu.Edit
if (!OperationInProgress.Value)
throw new InvalidOperationException($"Cannot {nameof(Update)} a rotate operation without calling {nameof(Begin)} first!");
Debug.Assert(objectsInRotation != null && originalPositions != null && originalPathControlPointPositions != null && defaultOrigin != null);
Debug.Assert(objectsInRotation != null && originalPositions != null && originalPathControlPointPositions != null && DefaultOrigin != null);
Vector2 actualOrigin = origin ?? defaultOrigin.Value;
Vector2 actualOrigin = origin ?? DefaultOrigin.Value;
foreach (var ho in objectsInRotation)
{
@ -103,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Edit
objectsInRotation = null;
originalPositions = null;
originalPathControlPointPositions = null;
defaultOrigin = null;
DefaultOrigin = null;
}
private IEnumerable<OsuHitObject> selectedMovableObjects => selectedItems.Cast<OsuHitObject>()

View File

@ -46,7 +46,6 @@ namespace osu.Game.Overlays.SkinEditor
private Drawable[]? objectsInRotation;
private Vector2? defaultOrigin;
private Dictionary<Drawable, float>? originalRotations;
private Dictionary<Drawable, Vector2>? originalPositions;
@ -60,7 +59,7 @@ namespace osu.Game.Overlays.SkinEditor
objectsInRotation = selectedItems.Cast<Drawable>().ToArray();
originalRotations = objectsInRotation.ToDictionary(d => d, d => d.Rotation);
originalPositions = objectsInRotation.ToDictionary(d => d, d => d.ToScreenSpace(d.OriginPosition));
defaultOrigin = GeometryUtils.GetSurroundingQuad(objectsInRotation.SelectMany(d => d.ScreenSpaceDrawQuad.GetVertices().ToArray())).Centre;
DefaultOrigin = GeometryUtils.GetSurroundingQuad(objectsInRotation.SelectMany(d => d.ScreenSpaceDrawQuad.GetVertices().ToArray())).Centre;
base.Begin();
}
@ -70,7 +69,7 @@ namespace osu.Game.Overlays.SkinEditor
if (objectsInRotation == null)
throw new InvalidOperationException($"Cannot {nameof(Update)} a rotate operation without calling {nameof(Begin)} first!");
Debug.Assert(originalRotations != null && originalPositions != null && defaultOrigin != null);
Debug.Assert(originalRotations != null && originalPositions != null && DefaultOrigin != null);
if (objectsInRotation.Length == 1 && origin == null)
{
@ -79,7 +78,7 @@ namespace osu.Game.Overlays.SkinEditor
return;
}
var actualOrigin = origin ?? defaultOrigin.Value;
var actualOrigin = origin ?? DefaultOrigin.Value;
foreach (var drawableItem in objectsInRotation)
{
@ -100,7 +99,7 @@ namespace osu.Game.Overlays.SkinEditor
objectsInRotation = null;
originalPositions = null;
originalRotations = null;
defaultOrigin = null;
DefaultOrigin = null;
base.Commit();
}

View File

@ -113,9 +113,13 @@ namespace osu.Game.Screens.Edit.Compose.Components
private float convertDragEventToAngleOfRotation(DragEvent e)
{
// Adjust coordinate system to the center of SelectionBox
float startAngle = MathF.Atan2(e.LastMousePosition.Y - selectionBox.DrawHeight / 2, e.LastMousePosition.X - selectionBox.DrawWidth / 2);
float endAngle = MathF.Atan2(e.MousePosition.Y - selectionBox.DrawHeight / 2, e.MousePosition.X - selectionBox.DrawWidth / 2);
// Adjust coordinate system to the center of the selection
Vector2 center = rotationHandler?.DefaultOrigin is not null
? selectionBox.ToLocalSpace(rotationHandler.ToScreenSpace(rotationHandler.DefaultOrigin.Value))
: selectionBox.DrawSize / 2;
float startAngle = MathF.Atan2(e.LastMousePosition.Y - center.Y, e.LastMousePosition.X - center.X);
float endAngle = MathF.Atan2(e.MousePosition.Y - center.Y, e.MousePosition.X - center.X);
return (endAngle - startAngle) * 180 / MathF.PI;
}

View File

@ -27,6 +27,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary>
public Bindable<bool> CanRotateAroundPlayfieldOrigin { get; private set; } = new BindableBool();
/// <summary>
/// Implementation-defined origin point to rotate around when no explicit origin is provided.
/// This field is only assigned during a rotation operation.
/// </summary>
public Vector2? DefaultOrigin { get; protected set; }
/// <summary>
/// Performs a single, instant, atomic rotation operation.
/// </summary>