mirror of
https://github.com/ppy/osu.git
synced 2026-05-21 21:00:42 +08:00
Merge pull request #33248 from chris-ehmann/fix-distance-snapping-to-stacks
Use stacked position when determining distance snap
This commit is contained in:
@@ -15,7 +15,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
public class OsuBeatmapProcessor : BeatmapProcessor
|
||||
{
|
||||
private const int stack_distance = 3;
|
||||
/// <summary>
|
||||
/// The maximum distance between the end of one object and the start of another
|
||||
/// which allows the objects to be stacked on top of another.
|
||||
/// </summary>
|
||||
public const int STACK_DISTANCE = 3;
|
||||
|
||||
public OsuBeatmapProcessor(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
@@ -93,8 +97,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
// We are no longer within stacking range of the next object.
|
||||
break;
|
||||
|
||||
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance
|
||||
|| (stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance))
|
||||
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < STACK_DISTANCE
|
||||
|| (stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < STACK_DISTANCE))
|
||||
{
|
||||
stackBaseIndex = n;
|
||||
|
||||
@@ -163,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
* o <- hitCircle has stack of -1
|
||||
* o <- hitCircle has stack of -2
|
||||
*/
|
||||
if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < STACK_DISTANCE)
|
||||
{
|
||||
int offset = objectI.StackHeight - objectN.StackHeight + 1;
|
||||
|
||||
@@ -171,7 +175,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
// For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
|
||||
OsuHitObject objectJ = hitObjects[j];
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < STACK_DISTANCE)
|
||||
objectJ.StackHeight -= offset;
|
||||
}
|
||||
|
||||
@@ -180,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
break;
|
||||
}
|
||||
|
||||
if (Vector2Extensions.Distance(objectN.Position, objectI.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.Position, objectI.Position) < STACK_DISTANCE)
|
||||
{
|
||||
// Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
|
||||
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
|
||||
@@ -204,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
// We are no longer within stacking range of the previous object.
|
||||
break;
|
||||
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < STACK_DISTANCE)
|
||||
{
|
||||
objectN.StackHeight = objectI.StackHeight + 1;
|
||||
objectI = objectN;
|
||||
@@ -245,12 +249,12 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
// Effects of this can be seen on https://osu.ppy.sh/beatmapsets/243#osu/1146 at sliders around 86647 ms, where
|
||||
// if we use `EndTime` here it would result in unexpected stacking.
|
||||
|
||||
if (Vector2Extensions.Distance(hitObjects[j].Position, currHitObject.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(hitObjects[j].Position, currHitObject.Position) < STACK_DISTANCE)
|
||||
{
|
||||
currHitObject.StackHeight++;
|
||||
startTime = hitObjects[j].StartTime;
|
||||
}
|
||||
else if (Vector2Extensions.Distance(hitObjects[j].Position, position2) < stack_distance)
|
||||
else if (Vector2Extensions.Distance(hitObjects[j].Position, position2) < STACK_DISTANCE)
|
||||
{
|
||||
// Case for sliders - bump notes down and right, rather than up and left.
|
||||
sliderStack++;
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osuTK;
|
||||
|
||||
@@ -16,10 +17,15 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public override double ReadCurrentDistanceSnap(HitObject before, HitObject after)
|
||||
{
|
||||
// If the pair of hit objects in question here could feasibly be on the same stack, do not provide a distance snap value -
|
||||
// they're likely too close to one another for the distance snap value to be useful anyway even if they somehow are not.
|
||||
if (Vector2.Distance(((OsuHitObject)before).EndPosition, ((OsuHitObject)after).Position) < OsuBeatmapProcessor.STACK_DISTANCE)
|
||||
return 0;
|
||||
|
||||
var lastObjectWithVelocity = EditorBeatmap.HitObjects.TakeWhile(ho => ho != after).OfType<IHasSliderVelocity>().LastOrDefault();
|
||||
|
||||
float expectedDistance = DurationToDistance(after.StartTime - before.GetEndTime(), before.StartTime, lastObjectWithVelocity);
|
||||
float actualDistance = Vector2.Distance(((OsuHitObject)before).EndPosition, ((OsuHitObject)after).Position);
|
||||
float actualDistance = Vector2.Distance(((OsuHitObject)before).StackedEndPosition, ((OsuHitObject)after).StackedPosition);
|
||||
|
||||
return actualDistance / expectedDistance;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user