mirror of
https://github.com/osukey/osukey.git
synced 2025-08-07 16:43:52 +09:00
Merge pull request #13337 from Pasi4K5/fix-sliders-out-of-screen
Fix sliders sometimes being outside of the playfield with osu! random mod enabled
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
@ -30,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
private static readonly float border_distance_x = OsuPlayfield.BASE_SIZE.X * playfield_edge_ratio;
|
private static readonly float border_distance_x = OsuPlayfield.BASE_SIZE.X * playfield_edge_ratio;
|
||||||
private static readonly float border_distance_y = OsuPlayfield.BASE_SIZE.Y * playfield_edge_ratio;
|
private static readonly float border_distance_y = OsuPlayfield.BASE_SIZE.Y * playfield_edge_ratio;
|
||||||
|
|
||||||
private static readonly Vector2 playfield_middle = Vector2.Divide(OsuPlayfield.BASE_SIZE, 2);
|
private static readonly Vector2 playfield_middle = OsuPlayfield.BASE_SIZE / 2;
|
||||||
|
|
||||||
private static readonly float playfield_diagonal = OsuPlayfield.BASE_SIZE.LengthFast;
|
private static readonly float playfield_diagonal = OsuPlayfield.BASE_SIZE.LengthFast;
|
||||||
|
|
||||||
@ -74,23 +75,9 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
// update end position as it may have changed as a result of the position update.
|
// update end position as it may have changed as a result of the position update.
|
||||||
current.EndPositionRandomised = current.PositionRandomised;
|
current.EndPositionRandomised = current.PositionRandomised;
|
||||||
|
|
||||||
switch (hitObject)
|
if (hitObject is Slider slider)
|
||||||
{
|
|
||||||
case Slider slider:
|
|
||||||
// Shift nested objects the same distance as the slider got shifted in the randomisation process
|
|
||||||
// so that moveSliderIntoPlayfield() can determine their relative distances to slider.Position and thus minMargin
|
|
||||||
shiftNestedObjects(slider, Vector2.Subtract(slider.Position, current.PositionOriginal));
|
|
||||||
|
|
||||||
var oldPos = new Vector2(slider.Position.X, slider.Position.Y);
|
|
||||||
|
|
||||||
moveSliderIntoPlayfield(slider, current);
|
moveSliderIntoPlayfield(slider, current);
|
||||||
|
|
||||||
// Shift them again to move them to their final position after the slider got moved into the playfield
|
|
||||||
shiftNestedObjects(slider, Vector2.Subtract(slider.Position, oldPos));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
|
|
||||||
current.AngleRad = (float)Math.Atan2(posRelativeToPrev.Y, posRelativeToPrev.X);
|
current.AngleRad = (float)Math.Atan2(posRelativeToPrev.Y, posRelativeToPrev.X);
|
||||||
|
|
||||||
var position = Vector2.Add(previous.EndPositionRandomised, posRelativeToPrev);
|
var position = previous.EndPositionRandomised + posRelativeToPrev;
|
||||||
|
|
||||||
// Move hit objects back into the playfield if they are outside of it,
|
// Move hit objects back into the playfield if they are outside of it,
|
||||||
// which would sometimes happen during big jumps otherwise.
|
// which would sometimes happen during big jumps otherwise.
|
||||||
@ -146,34 +133,41 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void moveSliderIntoPlayfield(Slider slider, RandomObjectInfo currentObjectInfo)
|
private void moveSliderIntoPlayfield(Slider slider, RandomObjectInfo currentObjectInfo)
|
||||||
{
|
{
|
||||||
// Min. distances from the slider's position to the playfield border
|
var minMargin = getMinSliderMargin(slider);
|
||||||
var minMargin = new MarginPadding();
|
|
||||||
|
|
||||||
foreach (var hitObject in slider.NestedHitObjects.Where(o => o is SliderTick || o is SliderEndCircle))
|
slider.Position = new Vector2(
|
||||||
{
|
Math.Clamp(slider.Position.X, minMargin.Left, OsuPlayfield.BASE_SIZE.X - minMargin.Right),
|
||||||
if (!(hitObject is OsuHitObject osuHitObject))
|
Math.Clamp(slider.Position.Y, minMargin.Top, OsuPlayfield.BASE_SIZE.Y - minMargin.Bottom)
|
||||||
continue;
|
);
|
||||||
|
|
||||||
var relativePos = Vector2.Subtract(osuHitObject.Position, slider.Position);
|
|
||||||
|
|
||||||
minMargin.Left = Math.Max(minMargin.Left, -relativePos.X);
|
|
||||||
minMargin.Right = Math.Max(minMargin.Right, relativePos.X);
|
|
||||||
minMargin.Top = Math.Max(minMargin.Top, -relativePos.Y);
|
|
||||||
minMargin.Bottom = Math.Max(minMargin.Bottom, relativePos.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slider.Position.X < minMargin.Left)
|
|
||||||
slider.Position = new Vector2(minMargin.Left, slider.Position.Y);
|
|
||||||
else if (slider.Position.X + minMargin.Right > OsuPlayfield.BASE_SIZE.X)
|
|
||||||
slider.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - minMargin.Right, slider.Position.Y);
|
|
||||||
|
|
||||||
if (slider.Position.Y < minMargin.Top)
|
|
||||||
slider.Position = new Vector2(slider.Position.X, minMargin.Top);
|
|
||||||
else if (slider.Position.Y + minMargin.Bottom > OsuPlayfield.BASE_SIZE.Y)
|
|
||||||
slider.Position = new Vector2(slider.Position.X, OsuPlayfield.BASE_SIZE.Y - minMargin.Bottom);
|
|
||||||
|
|
||||||
currentObjectInfo.PositionRandomised = slider.Position;
|
currentObjectInfo.PositionRandomised = slider.Position;
|
||||||
currentObjectInfo.EndPositionRandomised = slider.EndPosition;
|
currentObjectInfo.EndPositionRandomised = slider.EndPosition;
|
||||||
|
|
||||||
|
shiftNestedObjects(slider, currentObjectInfo.PositionRandomised - currentObjectInfo.PositionOriginal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the min. distances from the <see cref="Slider"/>'s position to the playfield border for the slider to be fully inside of the playfield.
|
||||||
|
/// </summary>
|
||||||
|
private MarginPadding getMinSliderMargin(Slider slider)
|
||||||
|
{
|
||||||
|
var pathPositions = new List<Vector2>();
|
||||||
|
slider.Path.GetPathToProgress(pathPositions, 0, 1);
|
||||||
|
|
||||||
|
var minMargin = new MarginPadding();
|
||||||
|
|
||||||
|
foreach (var pos in pathPositions)
|
||||||
|
{
|
||||||
|
minMargin.Left = Math.Max(minMargin.Left, -pos.X);
|
||||||
|
minMargin.Right = Math.Max(minMargin.Right, pos.X);
|
||||||
|
minMargin.Top = Math.Max(minMargin.Top, -pos.Y);
|
||||||
|
minMargin.Bottom = Math.Max(minMargin.Bottom, pos.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
minMargin.Left = Math.Min(minMargin.Left, OsuPlayfield.BASE_SIZE.X - minMargin.Right);
|
||||||
|
minMargin.Top = Math.Min(minMargin.Top, OsuPlayfield.BASE_SIZE.Y - minMargin.Bottom);
|
||||||
|
|
||||||
|
return minMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -188,7 +182,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
if (!(hitObject is OsuHitObject osuHitObject))
|
if (!(hitObject is OsuHitObject osuHitObject))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
osuHitObject.Position = Vector2.Add(osuHitObject.Position, shift);
|
osuHitObject.Position += shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user