mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 07:33:20 +08:00
Add support for converting sliders with repeats to streams
This commit is contained in:
parent
0cd3f98598
commit
8aa04864ce
@ -30,7 +30,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
|
||||
convertToStream();
|
||||
|
||||
AddAssert("stream created", () => streamCreatedFor(slider, 1 / 4d));
|
||||
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||
(time: 0, pathPosition: 0),
|
||||
(time: 0.25, pathPosition: 0.25),
|
||||
(time: 0.5, pathPosition: 0.5),
|
||||
(time: 0.75, pathPosition: 0.75),
|
||||
(time: 1, pathPosition: 1)));
|
||||
|
||||
AddStep("undo", () => Editor.Undo());
|
||||
AddAssert("slider restored", () => sliderRestored(slider));
|
||||
@ -44,7 +49,16 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
AddStep("change beat divisor", () => beatDivisor.Value = 8);
|
||||
|
||||
convertToStream();
|
||||
AddAssert("stream created", () => streamCreatedFor(slider, 1 / 8d));
|
||||
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||
(time: 0, pathPosition: 0),
|
||||
(time: 0.125, pathPosition: 0.125),
|
||||
(time: 0.25, pathPosition: 0.25),
|
||||
(time: 0.375, pathPosition: 0.375),
|
||||
(time: 0.5, pathPosition: 0.5),
|
||||
(time: 0.625, pathPosition: 0.625),
|
||||
(time: 0.75, pathPosition: 0.75),
|
||||
(time: 0.875, pathPosition: 0.875),
|
||||
(time: 1, pathPosition: 1)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -62,7 +76,32 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
|
||||
convertToStream();
|
||||
|
||||
AddAssert("stream created", () => streamCreatedFor(slider, 2 / 3d));
|
||||
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||
(time: 0, pathPosition: 0),
|
||||
(time: 2 / 3d, pathPosition: 2 / 3d)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConversionWithRepeats()
|
||||
{
|
||||
Slider slider = null;
|
||||
|
||||
AddStep("select first slider with repeats", () =>
|
||||
{
|
||||
slider = (Slider)EditorBeatmap.HitObjects.First(h => h is Slider s && s.RepeatCount > 0);
|
||||
EditorClock.Seek(slider.StartTime);
|
||||
EditorBeatmap.SelectedHitObjects.Add(slider);
|
||||
});
|
||||
AddStep("change beat divisor", () => beatDivisor.Value = 2);
|
||||
|
||||
convertToStream();
|
||||
|
||||
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||
(time: 0, pathPosition: 0),
|
||||
(time: 0.25, pathPosition: 0.5),
|
||||
(time: 0.5, pathPosition: 1),
|
||||
(time: 0.75, pathPosition: 0.5),
|
||||
(time: 1, pathPosition: 0)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -79,7 +118,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
|
||||
convertToStream();
|
||||
|
||||
AddAssert("stream created", () => streamCreatedFor(slider, 1 / 4d));
|
||||
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||
(time: 0, pathPosition: 0),
|
||||
(time: 0.25, pathPosition: 0.25),
|
||||
(time: 0.5, pathPosition: 0.5),
|
||||
(time: 0.75, pathPosition: 0.75),
|
||||
(time: 1, pathPosition: 1)));
|
||||
|
||||
AddStep("undo", () => Editor.Undo());
|
||||
AddAssert("slider restored", () => sliderRestored(slider));
|
||||
@ -97,18 +141,17 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
});
|
||||
}
|
||||
|
||||
private bool streamCreatedFor(Slider slider, double spacing)
|
||||
private bool streamCreatedFor(Slider slider, params (double time, double pathPosition)[] expectedCircles)
|
||||
{
|
||||
if (EditorBeatmap.HitObjects.Contains(slider))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i * spacing <= 1; ++i)
|
||||
foreach ((double expectedTime, double expectedPathPosition) in expectedCircles)
|
||||
{
|
||||
double progress = i * spacing;
|
||||
double time = slider.StartTime + progress * slider.Duration;
|
||||
Vector2 position = slider.Position + slider.Path.PositionAt(progress);
|
||||
double time = slider.StartTime + slider.Duration * expectedTime;
|
||||
Vector2 position = slider.Position + slider.Path.PositionAt(expectedPathPosition);
|
||||
|
||||
if (!EditorBeatmap.HitObjects.OfType<HitCircle>().Any(h => matches(h, time, position, slider.NewCombo && progress == 0)))
|
||||
if (!EditorBeatmap.HitObjects.OfType<HitCircle>().Any(h => matches(h, time, position, slider.NewCombo && expectedTime == 0)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
@ -268,7 +269,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
while (!Precision.DefinitelyBigger(time, HitObject.GetEndTime(), 1))
|
||||
{
|
||||
Vector2 position = HitObject.Position + HitObject.Path.PositionAt((time - HitObject.StartTime) / HitObject.Duration);
|
||||
// positionWithRepeats is a fractional number in the range of [0, HitObject.SpanCount()]
|
||||
// and indicates how many fractional spans of a slider have passed up to time.
|
||||
double positionWithRepeats = (time - HitObject.StartTime) / HitObject.Duration * HitObject.SpanCount();
|
||||
double pathPosition = positionWithRepeats - (int)positionWithRepeats;
|
||||
// every second span is in the reverse direction - need to reverse the path position.
|
||||
if (Precision.AlmostBigger(positionWithRepeats % 2, 1))
|
||||
pathPosition = 1 - pathPosition;
|
||||
|
||||
Vector2 position = HitObject.Position + HitObject.Path.PositionAt(pathPosition);
|
||||
|
||||
var samplePoint = (SampleControlPoint)HitObject.SampleControlPoint.DeepClone();
|
||||
samplePoint.Time = time;
|
||||
|
Loading…
Reference in New Issue
Block a user