mirror of
https://github.com/ppy/osu.git
synced 2025-02-15 13:22:57 +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.
|
// copy to mutate, as we will need to compare to the original later on.
|
||||||
var adjustedRect = selectionRect;
|
var adjustedRect = selectionRect;
|
||||||
|
bool isRotated = false;
|
||||||
// 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;
|
|
||||||
|
|
||||||
// for now aspect lock scale adjustments that occur at corners..
|
// for now aspect lock scale adjustments that occur at corners..
|
||||||
if (!anchor.HasFlagFast(Anchor.x1) && !anchor.HasFlagFast(Anchor.y1))
|
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.
|
// ..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).
|
// 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 (anchor.HasFlagFast(Anchor.x1))
|
||||||
// if dragging from the horizontal centre, only a vertical component is available.
|
// if dragging from the horizontal centre, only a vertical component is available.
|
||||||
scale.X = scale.Y / selectionRect.Height * selectionRect.Width;
|
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.x0)) adjustedRect.X -= scale.X;
|
||||||
if (anchor.HasFlagFast(Anchor.y0)) adjustedRect.Y -= scale.Y;
|
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.Width += scale.X;
|
||||||
adjustedRect.Height += scale.Y;
|
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.
|
// scale adjust applied to each individual item should match that of the quad itself.
|
||||||
var scaledDelta = new Vector2(
|
var scaledDelta = new Vector2(
|
||||||
MathF.Max(adjustedRect.Width / selectionRect.Width, 0),
|
adjustedRect.Width / selectionRect.Width,
|
||||||
MathF.Max(adjustedRect.Height / selectionRect.Height, 0)
|
adjustedRect.Height / selectionRect.Height
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (var b in SelectedBlueprints)
|
foreach (var b in SelectedBlueprints)
|
||||||
@ -102,7 +115,12 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
);
|
);
|
||||||
|
|
||||||
updateDrawablePosition(drawableItem, newPositionInAdjusted);
|
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;
|
return true;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.EnumExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
@ -307,6 +308,25 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
return button;
|
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)
|
private void addScaleHandle(Anchor anchor)
|
||||||
{
|
{
|
||||||
var handle = new SelectionBoxScaleHandle
|
var handle = new SelectionBoxScaleHandle
|
||||||
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.EnumExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
@ -69,6 +70,17 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
allDragHandles.Add(handle);
|
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 SelectionBoxRotationHandle displayedRotationHandle;
|
||||||
private SelectionBoxDragHandle activeHandle;
|
private SelectionBoxDragHandle activeHandle;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user