mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Merge pull request #24683 from Wleter/skin-editor-selection-negative-scaling
Allow inverse scaling selection in skin editor
This commit is contained in:
commit
ac3d7327df
@ -47,10 +47,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
// copy to mutate, as we will need to compare to the original later on.
|
||||
var adjustedRect = selectionRect;
|
||||
|
||||
// first, remove any scale axis we are not interested in.
|
||||
if (anchor.HasFlagFast(Anchor.x1)) scale.X = 0;
|
||||
if (anchor.HasFlagFast(Anchor.y1)) scale.Y = 0;
|
||||
bool isRotated = false;
|
||||
|
||||
// for now aspect lock scale adjustments that occur at corners..
|
||||
if (!anchor.HasFlagFast(Anchor.x1) && !anchor.HasFlagFast(Anchor.y1))
|
||||
@ -61,8 +58,9 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
}
|
||||
// ..or if any of the selection have been rotated.
|
||||
// this is to avoid requiring skew logic (which would likely not be the user's expected transform anyway).
|
||||
else if (SelectedBlueprints.Any(b => !Precision.AlmostEquals(((Drawable)b.Item).Rotation, 0)))
|
||||
else if (SelectedBlueprints.Any(b => !Precision.AlmostEquals(((Drawable)b.Item).Rotation % 90, 0)))
|
||||
{
|
||||
isRotated = true;
|
||||
if (anchor.HasFlagFast(Anchor.x1))
|
||||
// if dragging from the horizontal centre, only a vertical component is available.
|
||||
scale.X = scale.Y / selectionRect.Height * selectionRect.Width;
|
||||
@ -74,13 +72,28 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
if (anchor.HasFlagFast(Anchor.x0)) adjustedRect.X -= scale.X;
|
||||
if (anchor.HasFlagFast(Anchor.y0)) adjustedRect.Y -= scale.Y;
|
||||
|
||||
// Maintain the selection's centre position if dragging from the centre anchors and selection is rotated.
|
||||
if (isRotated && anchor.HasFlagFast(Anchor.x1)) adjustedRect.X -= scale.X / 2;
|
||||
if (isRotated && anchor.HasFlagFast(Anchor.y1)) adjustedRect.Y -= scale.Y / 2;
|
||||
|
||||
adjustedRect.Width += scale.X;
|
||||
adjustedRect.Height += scale.Y;
|
||||
|
||||
if (adjustedRect.Width <= 0 || adjustedRect.Height <= 0)
|
||||
{
|
||||
Axes toFlip = Axes.None;
|
||||
|
||||
if (adjustedRect.Width <= 0) toFlip |= Axes.X;
|
||||
if (adjustedRect.Height <= 0) toFlip |= Axes.Y;
|
||||
|
||||
SelectionBox.PerformFlipFromScaleHandles(toFlip);
|
||||
return true;
|
||||
}
|
||||
|
||||
// scale adjust applied to each individual item should match that of the quad itself.
|
||||
var scaledDelta = new Vector2(
|
||||
MathF.Max(adjustedRect.Width / selectionRect.Width, 0),
|
||||
MathF.Max(adjustedRect.Height / selectionRect.Height, 0)
|
||||
adjustedRect.Width / selectionRect.Width,
|
||||
adjustedRect.Height / selectionRect.Height
|
||||
);
|
||||
|
||||
foreach (var b in SelectedBlueprints)
|
||||
@ -102,7 +115,12 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
);
|
||||
|
||||
updateDrawablePosition(drawableItem, newPositionInAdjusted);
|
||||
drawableItem.Scale *= scaledDelta;
|
||||
|
||||
var currentScaledDelta = scaledDelta;
|
||||
if (Precision.AlmostEquals(MathF.Abs(drawableItem.Rotation) % 180, 90))
|
||||
currentScaledDelta = new Vector2(scaledDelta.Y, scaledDelta.X);
|
||||
|
||||
drawableItem.Scale *= currentScaledDelta;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -307,6 +308,25 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return button;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// This method should be called when a selection needs to be flipped
|
||||
/// because of an ongoing scale handle drag that would otherwise cause width or height to go negative.
|
||||
/// </remarks>
|
||||
public void PerformFlipFromScaleHandles(Axes axes)
|
||||
{
|
||||
if (axes.HasFlagFast(Axes.X))
|
||||
{
|
||||
dragHandles.FlipScaleHandles(Direction.Horizontal);
|
||||
OnFlip?.Invoke(Direction.Horizontal, false);
|
||||
}
|
||||
|
||||
if (axes.HasFlagFast(Axes.Y))
|
||||
{
|
||||
dragHandles.FlipScaleHandles(Direction.Vertical);
|
||||
OnFlip?.Invoke(Direction.Vertical, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void addScaleHandle(Anchor anchor)
|
||||
{
|
||||
var handle = new SelectionBoxScaleHandle
|
||||
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
@ -69,6 +70,17 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
allDragHandles.Add(handle);
|
||||
}
|
||||
|
||||
public void FlipScaleHandles(Direction direction)
|
||||
{
|
||||
foreach (var handle in scaleHandles)
|
||||
{
|
||||
if (direction == Direction.Horizontal && !handle.Anchor.HasFlagFast(Anchor.x1))
|
||||
handle.Anchor ^= Anchor.x0 | Anchor.x2;
|
||||
if (direction == Direction.Vertical && !handle.Anchor.HasFlagFast(Anchor.y1))
|
||||
handle.Anchor ^= Anchor.y0 | Anchor.y2;
|
||||
}
|
||||
}
|
||||
|
||||
private SelectionBoxRotationHandle displayedRotationHandle;
|
||||
private SelectionBoxDragHandle activeHandle;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user