1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 09:23:06 +08:00

Merge pull request #20941 from peppy/fix-distance-snap-offset

Offset start of distance snap grid drawing if reference object's start time doesn't align
This commit is contained in:
Dan Balasescu 2022-10-26 13:46:31 +09:00 committed by GitHub
commit 72b594d72e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 4 deletions

View File

@ -4,12 +4,15 @@
#nullable disable
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Overlays;
@ -52,6 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
};
private OsuDistanceSnapGrid grid;
private SnappingCursorContainer cursor;
public TestSceneOsuDistanceSnapGrid()
{
@ -88,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
RelativeSizeAxes = Axes.Both,
Colour = Color4.SlateGray
},
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }),
new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position }
};
});
@ -154,6 +158,37 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
assertSnappedDistance(expectedDistance);
}
[Test]
public void TestReferenceObjectNotOnSnapGrid()
{
AddStep("create grid", () =>
{
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.SlateGray
},
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
grid = new OsuDistanceSnapGrid(new HitCircle
{
Position = grid_position,
// This is important. It sets the reference object to a point in time that isn't on the current snap divisor's grid.
// We are testing that the grid's display is offset correctly.
StartTime = 40,
}),
};
});
AddStep("move mouse to point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2(beat_length, 0) * 2)));
AddAssert("Ensure cursor is on a grid line", () =>
{
return grid.ChildrenOfType<CircularProgress>().Any(p => Precision.AlmostEquals(p.ScreenSpaceDrawQuad.TopRight.X, grid.ToScreenSpace(cursor.LastSnappedPosition).X));
});
}
[Test]
public void TestLimitedDistance()
{
@ -166,8 +201,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
RelativeSizeAxes = Axes.Both,
Colour = Color4.SlateGray
},
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }, new HitCircle { StartTime = 200 }),
new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position }
};
});
@ -186,6 +221,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
{
public Func<Vector2, Vector2> GetSnapPosition;
public Vector2 LastSnappedPosition { get; private set; }
private readonly Drawable cursor;
private InputManager inputManager;
@ -214,7 +251,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
protected override void Update()
{
base.Update();
cursor.Position = GetSnapPosition.Invoke(inputManager.CurrentState.Mouse.Position);
cursor.Position = LastSnappedPosition = GetSnapPosition.Invoke(inputManager.CurrentState.Mouse.Position);
}
}
}

View File

@ -53,9 +53,16 @@ namespace osu.Game.Screens.Edit.Compose.Components
float maxDistance = new Vector2(dx, dy).Length;
int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceBetweenTicks));
// We need to offset the drawn lines to the next valid snap for the currently selected divisor.
//
// Picture the scenario where the user has just placed an object on a 1/2 snap, then changes to
// 1/3 snap and expects to be able to place the next object on a valid 1/3 snap, regardless of the
// fact that the 1/2 snap reference object is not valid for 1/3 snapping.
float offset = SnapProvider.FindSnappedDistance(ReferenceObject, 0);
for (int i = 0; i < requiredCircles; i++)
{
float diameter = (i + 1) * DistanceBetweenTicks * 2;
float diameter = (offset + (i + 1) * DistanceBetweenTicks) * 2;
AddInternal(new Ring(ReferenceObject, GetColourForIndexFromPlacement(i))
{