mirror of
https://github.com/ppy/osu.git
synced 2024-12-16 10:23:04 +08:00
use minimum enclosing circle selection centre in rotation
This commit is contained in:
parent
59ab71f786
commit
ee00624751
@ -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>()
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user