mirror of https://github.com/ppy/osu
Merge pull request #30281 from bdach/remove-irrelevant-hacks
Fix slider ticks and repeats incorrectly moved to position of head when strict tracking and any conversion mod that moves objects is active
This commit is contained in:
commit
80c77e6e05
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public partial class TestSceneOsuModMirror : OsuModTestScene
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCorrectReflections([Values] OsuModMirror.MirrorType type, [Values] bool withStrictTracking) => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Autoplay = true,
|
||||||
|
Beatmap = new OsuBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
Position = new Vector2(0),
|
||||||
|
Path = new SliderPath
|
||||||
|
{
|
||||||
|
ControlPoints =
|
||||||
|
{
|
||||||
|
new PathControlPoint(),
|
||||||
|
new PathControlPoint(new Vector2(100, 0))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TickDistanceMultiplier = 0.5,
|
||||||
|
RepeatCount = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Mods = withStrictTracking
|
||||||
|
? [new OsuModMirror { Reflection = { Value = type } }, new OsuModStrictTracking()]
|
||||||
|
: [new OsuModMirror { Reflection = { Value = type } }],
|
||||||
|
PassCondition = () =>
|
||||||
|
{
|
||||||
|
var slider = this.ChildrenOfType<DrawableSlider>().SingleOrDefault();
|
||||||
|
var playfield = this.ChildrenOfType<OsuPlayfield>().Single();
|
||||||
|
|
||||||
|
if (slider == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Precision.AlmostEquals(playfield.ToLocalSpace(slider.HeadCircle.ScreenSpaceDrawQuad.Centre), slider.HitObject.Position)
|
||||||
|
&& Precision.AlmostEquals(playfield.ToLocalSpace(slider.TailCircle.ScreenSpaceDrawQuad.Centre), slider.HitObject.Position)
|
||||||
|
&& Precision.AlmostEquals(playfield.ToLocalSpace(slider.NestedHitObjects.OfType<DrawableSliderRepeat>().Single().ScreenSpaceDrawQuad.Centre),
|
||||||
|
slider.HitObject.Position + slider.HitObject.Path.PositionAt(1))
|
||||||
|
&& Precision.AlmostEquals(playfield.ToLocalSpace(slider.NestedHitObjects.OfType<DrawableSliderTick>().First().ScreenSpaceDrawQuad.Centre),
|
||||||
|
slider.HitObject.Position + slider.HitObject.Path.PositionAt(0.7f));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -120,6 +120,7 @@ protected override void CreateNestedHitObjects(CancellationToken cancellationTok
|
||||||
Position = Position + Path.PositionAt(e.PathProgress),
|
Position = Position + Path.PositionAt(e.PathProgress),
|
||||||
StackHeight = StackHeight,
|
StackHeight = StackHeight,
|
||||||
Scale = Scale,
|
Scale = Scale,
|
||||||
|
PathProgress = e.PathProgress,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -150,6 +151,7 @@ protected override void CreateNestedHitObjects(CancellationToken cancellationTok
|
||||||
Position = Position + Path.PositionAt(e.PathProgress),
|
Position = Position + Path.PositionAt(e.PathProgress),
|
||||||
StackHeight = StackHeight,
|
StackHeight = StackHeight,
|
||||||
Scale = Scale,
|
Scale = Scale,
|
||||||
|
PathProgress = e.PathProgress,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
@ -117,10 +116,9 @@ public static void ReflectHorizontallyAlongPlayfield(OsuHitObject osuObject)
|
||||||
if (osuObject is not Slider slider)
|
if (osuObject is not Slider slider)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void reflectNestedObject(OsuHitObject nested) => nested.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - nested.Position.X, nested.Position.Y);
|
|
||||||
static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y);
|
static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y);
|
||||||
|
|
||||||
modifySlider(slider, reflectNestedObject, reflectControlPoint);
|
modifySlider(slider, reflectControlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -134,10 +132,9 @@ public static void ReflectVerticallyAlongPlayfield(OsuHitObject osuObject)
|
||||||
if (osuObject is not Slider slider)
|
if (osuObject is not Slider slider)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void reflectNestedObject(OsuHitObject nested) => nested.Position = new Vector2(nested.Position.X, OsuPlayfield.BASE_SIZE.Y - nested.Position.Y);
|
|
||||||
static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(point.Position.X, -point.Position.Y);
|
static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(point.Position.X, -point.Position.Y);
|
||||||
|
|
||||||
modifySlider(slider, reflectNestedObject, reflectControlPoint);
|
modifySlider(slider, reflectControlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -146,10 +143,9 @@ public static void ReflectVerticallyAlongPlayfield(OsuHitObject osuObject)
|
||||||
/// <param name="slider">The slider to be flipped.</param>
|
/// <param name="slider">The slider to be flipped.</param>
|
||||||
public static void FlipSliderInPlaceHorizontally(Slider slider)
|
public static void FlipSliderInPlaceHorizontally(Slider slider)
|
||||||
{
|
{
|
||||||
void flipNestedObject(OsuHitObject nested) => nested.Position = new Vector2(slider.X - (nested.X - slider.X), nested.Y);
|
|
||||||
static void flipControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y);
|
static void flipControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y);
|
||||||
|
|
||||||
modifySlider(slider, flipNestedObject, flipControlPoint);
|
modifySlider(slider, flipControlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -159,18 +155,13 @@ public static void FlipSliderInPlaceHorizontally(Slider slider)
|
||||||
/// <param name="rotation">The angle, measured in radians, to rotate the slider by.</param>
|
/// <param name="rotation">The angle, measured in radians, to rotate the slider by.</param>
|
||||||
public static void RotateSlider(Slider slider, float rotation)
|
public static void RotateSlider(Slider slider, float rotation)
|
||||||
{
|
{
|
||||||
void rotateNestedObject(OsuHitObject nested) => nested.Position = rotateVector(nested.Position - slider.Position, rotation) + slider.Position;
|
|
||||||
void rotateControlPoint(PathControlPoint point) => point.Position = rotateVector(point.Position, rotation);
|
void rotateControlPoint(PathControlPoint point) => point.Position = rotateVector(point.Position, rotation);
|
||||||
|
|
||||||
modifySlider(slider, rotateNestedObject, rotateControlPoint);
|
modifySlider(slider, rotateControlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void modifySlider(Slider slider, Action<OsuHitObject> modifyNestedObject, Action<PathControlPoint> modifyControlPoint)
|
private static void modifySlider(Slider slider, Action<PathControlPoint> modifyControlPoint)
|
||||||
{
|
{
|
||||||
// No need to update the head and tail circles, since slider handles that when the new slider path is set
|
|
||||||
slider.NestedHitObjects.OfType<SliderTick>().ForEach(modifyNestedObject);
|
|
||||||
slider.NestedHitObjects.OfType<SliderRepeat>().ForEach(modifyNestedObject);
|
|
||||||
|
|
||||||
var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position, p.Type)).ToArray();
|
var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position, p.Type)).ToArray();
|
||||||
foreach (var point in controlPoints)
|
foreach (var point in controlPoints)
|
||||||
modifyControlPoint(point);
|
modifyControlPoint(point);
|
||||||
|
|
Loading…
Reference in New Issue