1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 03:27:24 +08:00

fix rotated scale bounds again

This commit is contained in:
OliBomby 2024-07-14 16:58:05 +02:00
parent ae38002777
commit 58eb7f6fe1
2 changed files with 73 additions and 7 deletions

View File

@ -69,6 +69,7 @@ namespace osu.Game.Rulesets.Osu.Edit
private Dictionary<OsuHitObject, OriginalHitObjectState>? objectsInScale;
private Vector2? defaultOrigin;
private List<Vector2>? originalConvexHull;
public override void Begin()
{
@ -84,6 +85,9 @@ namespace osu.Game.Rulesets.Osu.Edit
? GeometryUtils.GetSurroundingQuad(slider.Path.ControlPoints.Select(p => slider.Position + p.Position))
: GeometryUtils.GetSurroundingQuad(objectsInScale.Keys);
defaultOrigin = OriginalSurroundingQuad.Value.Centre;
originalConvexHull = objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider2
? GeometryUtils.GetConvexHull(slider2.Path.ControlPoints.Select(p => slider2.Position + p.Position))
: GeometryUtils.GetConvexHull(objectsInScale.Keys);
}
public override void Update(Vector2 scale, Vector2? origin = null, Axes adjustAxis = Axes.Both, float axisRotation = 0)
@ -211,12 +215,31 @@ namespace osu.Game.Rulesets.Osu.Edit
if (objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider)
origin = slider.Position;
float cos = MathF.Cos(float.DegreesToRadians(-axisRotation));
float sin = MathF.Sin(float.DegreesToRadians(-axisRotation));
scale = clampScaleToAdjustAxis(scale, adjustAxis);
Vector2 actualOrigin = origin ?? defaultOrigin.Value;
var selectionQuad = OriginalSurroundingQuad.Value;
IEnumerable<Vector2> points;
scale = clampToBound(scale, selectionQuad.BottomRight, OsuPlayfield.BASE_SIZE);
scale = clampToBound(scale, selectionQuad.TopLeft, Vector2.Zero);
if (axisRotation == 0)
{
var selectionQuad = OriginalSurroundingQuad.Value;
points = new[]
{
selectionQuad.TopLeft,
selectionQuad.TopRight,
selectionQuad.BottomLeft,
selectionQuad.BottomRight
};
}
else
points = originalConvexHull!;
foreach (var point in points)
{
scale = clampToBound(scale, point, Vector2.Zero);
scale = clampToBound(scale, point, OsuPlayfield.BASE_SIZE);
}
return Vector2.ComponentMax(scale, new Vector2(Precision.FLOAT_EPSILON));
@ -226,8 +249,6 @@ namespace osu.Game.Rulesets.Osu.Edit
{
p -= actualOrigin;
bound -= actualOrigin;
float cos = MathF.Cos(float.DegreesToRadians(-axisRotation));
float sin = MathF.Sin(float.DegreesToRadians(-axisRotation));
var a = new Vector2(cos * cos * p.X - sin * cos * p.Y, -sin * cos * p.X + sin * sin * p.Y);
var b = new Vector2(sin * sin * p.X + sin * cos * p.Y, sin * cos * p.X + cos * cos * p.Y);

View File

@ -138,7 +138,52 @@ namespace osu.Game.Utils
/// </summary>
/// <param name="hitObjects">The hit objects to calculate a quad for.</param>
public static Quad GetSurroundingQuad(IEnumerable<IHasPosition> hitObjects) =>
GetSurroundingQuad(hitObjects.SelectMany(h =>
GetSurroundingQuad(enumerateStartAndEndPositions(hitObjects));
/// <summary>
/// Returns the points that make up the convex hull of the provided points.
/// </summary>
/// <param name="points">The points to calculate a convex hull.</param>
public static List<Vector2> GetConvexHull(IEnumerable<Vector2> points)
{
List<Vector2> p = points.ToList();
if (p.Count <= 1)
return p;
int n = p.Count, k = 0;
List<Vector2> hull = new List<Vector2>(new Vector2[2 * n]);
p.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X));
// Build lower hull
for (int i = 0; i < n; ++i)
{
while (k >= 2 && cross(hull[k - 2], hull[k - 1], p[i]) <= 0)
k--;
hull[k] = p[i];
k++;
}
// Build upper hull
for (int i = n - 2, t = k + 1; i >= 0; i--)
{
while (k >= t && cross(hull[k - 2], hull[k - 1], p[i]) <= 0)
k--;
hull[k] = p[i];
k++;
}
return hull.Take(k - 1).ToList();
float cross(Vector2 o, Vector2 a, Vector2 b) => (a.X - o.X) * (b.Y - o.Y) - (a.Y - o.Y) * (b.X - o.X);
}
public static List<Vector2> GetConvexHull(IEnumerable<IHasPosition> hitObjects) =>
GetConvexHull(enumerateStartAndEndPositions(hitObjects));
private static IEnumerable<Vector2> enumerateStartAndEndPositions(IEnumerable<IHasPosition> hitObjects) =>
hitObjects.SelectMany(h =>
{
if (h is IHasPath path)
{
@ -151,6 +196,6 @@ namespace osu.Game.Utils
}
return new[] { h.Position };
}));
});
}
}