1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 06:57:39 +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>
private Vector2? referenceOrigin;
public override bool HandleScaleY(in float 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)
public override bool HandleScale(Vector2 scale, Anchor reference)
{
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;
// 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;
}
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)
{
var hitObjects = selectedMovableObjects;

View File

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

View File

@ -17,8 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
public class ComposeSelectionBox : CompositeDrawable
{
public Action<DragEvent> OnRotation;
public Action<DragEvent, Anchor> OnScaleX;
public Action<DragEvent, Anchor> OnScaleY;
public Action<DragEvent, Anchor> OnScale;
public Action OperationStarted;
public Action OperationEnded;
@ -128,20 +127,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
AddRangeInternal(new[]
{
new DragHandle
{
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
},
createDragHandle(Anchor.TopCentre),
createDragHandle(Anchor.BottomCentre),
});
}
@ -149,20 +136,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
AddRangeInternal(new[]
{
new DragHandle
{
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
},
createDragHandle(Anchor.CentreLeft),
createDragHandle(Anchor.CentreRight),
});
}
@ -170,52 +145,20 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
AddRangeInternal(new[]
{
new DragHandle
{
Anchor = Anchor.TopLeft,
HandleDrag = e =>
{
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
},
createDragHandle(Anchor.TopLeft),
createDragHandle(Anchor.TopRight),
createDragHandle(Anchor.BottomLeft),
createDragHandle(Anchor.BottomRight),
});
}
ScaleDragHandle createDragHandle(Anchor anchor) =>
new ScaleDragHandle(anchor)
{
HandleDrag = e => OnScale?.Invoke(e, anchor),
OperationStarted = operationStarted,
OperationEnded = operationEnded
};
}
private int activeOperations;
@ -232,6 +175,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
OperationStarted?.Invoke();
}
private class ScaleDragHandle : DragHandle
{
public ScaleDragHandle(Anchor anchor)
{
Anchor = anchor;
}
}
private class RotationDragHandle : DragHandle
{
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.
using System;
@ -101,8 +101,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
OperationEnded = OnDragOperationEnded,
OnRotation = e => HandleRotation(e.Delta.X),
OnScaleX = (e, anchor) => HandleScaleX(e.Delta.X, anchor),
OnScaleY = (e, anchor) => HandleScaleY(e.Delta.Y, anchor),
OnScale = (e, anchor) => HandleScale(e.Delta, anchor),
};
/// <summary>
@ -145,20 +144,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
public virtual bool HandleRotation(float angle) => false;
/// <summary>
/// Handles the selected <see cref="DrawableHitObject"/>s being scaled in a vertical direction.
/// Handles the selected <see cref="DrawableHitObject"/>s being scaled.
/// </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>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
public virtual bool HandleScaleY(in float 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 virtual bool HandleScale(Vector2 scale, Anchor anchor) => false;
public bool OnPressed(PlatformAction action)
{