diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index ad2f4585f6..98488fef8c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -98,13 +98,9 @@ namespace osu.Game.Rulesets.Osu.Mods switch (hitObject) { case Slider slider: + shiftNestedObjects(slider, Vector2.Subtract(slider.Position, currentObjectInfo.PositionOriginal)); moveSliderIntoPlayfield(ref slider, ref currentObjectInfo); - var sliderShift = Vector2.Subtract(slider.Position, currentObjectInfo.PositionOriginal); - - foreach (var tick in slider.NestedHitObjects.OfType()) - tick.Position = Vector2.Add(tick.Position, sliderShift); - break; } @@ -158,27 +154,61 @@ namespace osu.Game.Rulesets.Osu.Mods currentObjectInfo.PositionRandomised = position; } + /// + /// Moves the and all necessary nested s into the if they aren't already. + /// private void moveSliderIntoPlayfield(ref Slider slider, ref RandomObjectInfo currentObjectInfo) { - foreach (var controlPoint in slider.Path.ControlPoints) + var oldPos = new Vector2(slider.Position.X, slider.Position.Y); + + // Min. distances from the slider's position to the playfield border + var minMargin = new MarginPadding(0); + + foreach (var hitObject in slider.NestedHitObjects.Where(o => o is SliderTick || o is SliderEndCircle)) { - // Position of controlPoint relative to slider.Position - var pos = controlPoint.Position.Value; + if (!(hitObject is OsuHitObject osuHitObject)) + continue; - var playfieldSize = OsuPlayfield.BASE_SIZE; + var relativePos = Vector2.Subtract(osuHitObject.Position, slider.Position); - if (pos.X + slider.Position.X < 0) - slider.Position = new Vector2(-pos.X, slider.Position.Y); - else if (pos.X + slider.Position.X > playfieldSize.X) - slider.Position = new Vector2(playfieldSize.X - pos.X, slider.Position.Y); - - if (pos.Y + slider.Position.Y < 0) - slider.Position = new Vector2(slider.Position.X, -pos.Y); - else if (pos.Y + slider.Position.Y > playfieldSize.Y) - slider.Position = new Vector2(slider.Position.X, playfieldSize.Y - pos.Y); + 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); } - currentObjectInfo.EndPositionRandomised = slider.TailCircle.Position; + 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.EndPositionRandomised = slider.EndPosition; + + var shift = Vector2.Subtract(slider.Position, oldPos); + + shiftNestedObjects(slider, shift); + } + + /// + /// Shifts all nested s and s by the specified shift. + /// + /// whose nested s and s should be shifted + /// The the 's nested s and s should be shifted by + private void shiftNestedObjects(Slider slider, Vector2 shift) + { + foreach (var hitObject in slider.NestedHitObjects.Where(o => o is SliderTick || o is SliderRepeat)) + { + if (!(hitObject is OsuHitObject osuHitObject)) + continue; + + osuHitObject.Position = Vector2.Add(osuHitObject.Position, shift); + } } ///