1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 09:47:52 +08:00

Combine scale operations and tidy up scale drag handle construction

This commit is contained in:
Dean Herbert 2020-09-30 15:08:56 +09:00
parent 313b0d149f
commit f1298bed79
4 changed files with 77 additions and 130 deletions

View File

@ -41,37 +41,16 @@ namespace osu.Game.Rulesets.Osu.Edit
/// </summary> /// </summary>
private Vector2? referenceOrigin; private Vector2? referenceOrigin;
public override bool HandleScaleY(in float scale, Anchor reference) => public override bool HandleScale(Vector2 scale, Anchor reference)
scaleSelection(new Vector2(0, ((reference & Anchor.y0) > 0 ? -1 : 1) * scale), reference);
public override bool HandleScaleX(in float scale, Anchor reference) =>
scaleSelection(new Vector2(((reference & Anchor.x0) > 0 ? -1 : 1) * scale, 0), reference);
public override bool HandleRotation(float delta)
{ {
var hitObjects = selectedMovableObjects; // cancel out scale in axes we don't care about (based on which drag handle was used).
if ((reference & Anchor.x1) > 0) scale.X = 0;
if ((reference & Anchor.y1) > 0) scale.Y = 0;
Quad quad = getSurroundingQuad(hitObjects); // reverse the scale direction if dragging from top or left.
if ((reference & Anchor.x0) > 0) scale.X = -scale.X;
if ((reference & Anchor.y0) > 0) scale.Y = -scale.Y;
referenceOrigin ??= quad.Centre;
foreach (var h in hitObjects)
{
h.Position = rotatePointAroundOrigin(h.Position, referenceOrigin.Value, delta);
if (h is IHasPath path)
{
foreach (var point in path.Path.ControlPoints)
point.Position.Value = rotatePointAroundOrigin(point.Position.Value, Vector2.Zero, delta);
}
}
// this isn't always the case but let's be lenient for now.
return true;
}
private bool scaleSelection(Vector2 scale, Anchor reference)
{
var hitObjects = selectedMovableObjects; var hitObjects = selectedMovableObjects;
// for the time being, allow resizing of slider paths only if the slider is // for the time being, allow resizing of slider paths only if the slider is
@ -110,6 +89,29 @@ namespace osu.Game.Rulesets.Osu.Edit
return true; return true;
} }
public override bool HandleRotation(float delta)
{
var hitObjects = selectedMovableObjects;
Quad quad = getSurroundingQuad(hitObjects);
referenceOrigin ??= quad.Centre;
foreach (var h in hitObjects)
{
h.Position = rotatePointAroundOrigin(h.Position, referenceOrigin.Value, delta);
if (h is IHasPath path)
{
foreach (var point in path.Path.ControlPoints)
point.Position.Value = rotatePointAroundOrigin(point.Position.Value, Vector2.Zero, delta);
}
}
// this isn't always the case but let's be lenient for now.
return true;
}
private bool moveSelection(Vector2 delta) private bool moveSelection(Vector2 delta)
{ {
var hitObjects = selectedMovableObjects; var hitObjects = selectedMovableObjects;

View File

@ -32,8 +32,7 @@ namespace osu.Game.Tests.Visual.Editing
CanScaleY = true, CanScaleY = true,
OnRotation = handleRotation, OnRotation = handleRotation,
OnScaleX = handleScaleX, OnScale = handleScale
OnScaleY = handleScaleY,
} }
} }
}); });
@ -43,24 +42,28 @@ namespace osu.Game.Tests.Visual.Editing
AddToggleStep("toggle y", state => selectionBox.CanScaleY = state); AddToggleStep("toggle y", state => selectionBox.CanScaleY = state);
} }
private void handleScaleY(DragEvent e, Anchor reference) private void handleScale(DragEvent e, Anchor reference)
{ {
int direction = (reference & Anchor.y0) > 0 ? -1 : 1; if ((reference & Anchor.y1) == 0)
if (direction < 0) {
selectionArea.Y += e.Delta.Y; int directionY = (reference & Anchor.y0) > 0 ? -1 : 1;
selectionArea.Height += direction * e.Delta.Y; if (directionY < 0)
} selectionArea.Y += e.Delta.Y;
selectionArea.Height += directionY * e.Delta.Y;
}
private void handleScaleX(DragEvent e, Anchor reference) if ((reference & Anchor.x1) == 0)
{ {
int direction = (reference & Anchor.x0) > 0 ? -1 : 1; int directionX = (reference & Anchor.x0) > 0 ? -1 : 1;
if (direction < 0) if (directionX < 0)
selectionArea.X += e.Delta.X; selectionArea.X += e.Delta.X;
selectionArea.Width += direction * e.Delta.X; selectionArea.Width += directionX * e.Delta.X;
}
} }
private void handleRotation(DragEvent e) private void handleRotation(DragEvent e)
{ {
// kinda silly and wrong, but just showing that the drag handles work.
selectionArea.Rotation += e.Delta.X; selectionArea.Rotation += e.Delta.X;
} }
} }

View File

@ -17,8 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
public class ComposeSelectionBox : CompositeDrawable public class ComposeSelectionBox : CompositeDrawable
{ {
public Action<DragEvent> OnRotation; public Action<DragEvent> OnRotation;
public Action<DragEvent, Anchor> OnScaleX; public Action<DragEvent, Anchor> OnScale;
public Action<DragEvent, Anchor> OnScaleY;
public Action OperationStarted; public Action OperationStarted;
public Action OperationEnded; public Action OperationEnded;
@ -128,20 +127,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
AddRangeInternal(new[] AddRangeInternal(new[]
{ {
new DragHandle createDragHandle(Anchor.TopCentre),
{ createDragHandle(Anchor.BottomCentre),
Anchor = Anchor.TopCentre,
HandleDrag = e => OnScaleY?.Invoke(e, Anchor.TopCentre),
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
new DragHandle
{
Anchor = Anchor.BottomCentre,
HandleDrag = e => OnScaleY?.Invoke(e, Anchor.BottomCentre),
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
}); });
} }
@ -149,20 +136,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
AddRangeInternal(new[] AddRangeInternal(new[]
{ {
new DragHandle createDragHandle(Anchor.CentreLeft),
{ createDragHandle(Anchor.CentreRight),
Anchor = Anchor.CentreLeft,
HandleDrag = e => OnScaleX?.Invoke(e, Anchor.CentreLeft),
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
new DragHandle
{
Anchor = Anchor.CentreRight,
HandleDrag = e => OnScaleX?.Invoke(e, Anchor.CentreRight),
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
}); });
} }
@ -170,52 +145,20 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
AddRangeInternal(new[] AddRangeInternal(new[]
{ {
new DragHandle createDragHandle(Anchor.TopLeft),
{ createDragHandle(Anchor.TopRight),
Anchor = Anchor.TopLeft, createDragHandle(Anchor.BottomLeft),
HandleDrag = e => createDragHandle(Anchor.BottomRight),
{
OnScaleX?.Invoke(e, Anchor.TopLeft);
OnScaleY?.Invoke(e, Anchor.TopLeft);
},
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
new DragHandle
{
Anchor = Anchor.TopRight,
HandleDrag = e =>
{
OnScaleX?.Invoke(e, Anchor.TopRight);
OnScaleY?.Invoke(e, Anchor.TopRight);
},
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
new DragHandle
{
Anchor = Anchor.BottomLeft,
HandleDrag = e =>
{
OnScaleX?.Invoke(e, Anchor.BottomLeft);
OnScaleY?.Invoke(e, Anchor.BottomLeft);
},
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
new DragHandle
{
Anchor = Anchor.BottomRight,
HandleDrag = e =>
{
OnScaleX?.Invoke(e, Anchor.BottomRight);
OnScaleY?.Invoke(e, Anchor.BottomRight);
},
OperationStarted = operationStarted,
OperationEnded = operationEnded
},
}); });
} }
ScaleDragHandle createDragHandle(Anchor anchor) =>
new ScaleDragHandle(anchor)
{
HandleDrag = e => OnScale?.Invoke(e, anchor),
OperationStarted = operationStarted,
OperationEnded = operationEnded
};
} }
private int activeOperations; private int activeOperations;
@ -232,6 +175,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
OperationStarted?.Invoke(); OperationStarted?.Invoke();
} }
private class ScaleDragHandle : DragHandle
{
public ScaleDragHandle(Anchor anchor)
{
Anchor = anchor;
}
}
private class RotationDragHandle : DragHandle private class RotationDragHandle : DragHandle
{ {
private SpriteIcon icon; private SpriteIcon icon;

View File

@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System; using System;
@ -101,8 +101,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
OperationEnded = OnDragOperationEnded, OperationEnded = OnDragOperationEnded,
OnRotation = e => HandleRotation(e.Delta.X), OnRotation = e => HandleRotation(e.Delta.X),
OnScaleX = (e, anchor) => HandleScaleX(e.Delta.X, anchor), OnScale = (e, anchor) => HandleScale(e.Delta, anchor),
OnScaleY = (e, anchor) => HandleScaleY(e.Delta.Y, anchor),
}; };
/// <summary> /// <summary>
@ -145,20 +144,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
public virtual bool HandleRotation(float angle) => false; public virtual bool HandleRotation(float angle) => false;
/// <summary> /// <summary>
/// Handles the selected <see cref="DrawableHitObject"/>s being scaled in a vertical direction. /// Handles the selected <see cref="DrawableHitObject"/>s being scaled.
/// </summary> /// </summary>
/// <param name="scale">The delta scale to apply.</param> /// <param name="scale">The delta scale to apply, in playfield local coordinates.</param>
/// <param name="anchor">The point of reference where the scale is originating from.</param> /// <param name="anchor">The point of reference where the scale is originating from.</param>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns> /// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
public virtual bool HandleScaleY(in float scale, Anchor anchor) => false; public virtual bool HandleScale(Vector2 scale, Anchor anchor) => false;
/// <summary>
/// Handles the selected <see cref="DrawableHitObject"/>s being scaled in a horizontal direction.
/// </summary>
/// <param name="scale">The delta scale to apply.</param>
/// <param name="anchor">The point of reference where the scale is originating from.</param>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
public virtual bool HandleScaleX(in float scale, Anchor anchor) => false;
public bool OnPressed(PlatformAction action) public bool OnPressed(PlatformAction action)
{ {