private void convertToStream() { if (editorBeatmap == null || changeHandler == null || beatDivisor == null) { return; } var timingPoint = editorBeatmap.ControlPointInfo.TimingPointAt(HitObject.StartTime); double streamSpacing = timingPoint.BeatLength / beatDivisor.Value; changeHandler.BeginChange(); int i = 0; double time = HitObject.StartTime; while (!Precision.DefinitelyBigger(time, HitObject.GetEndTime(), 1)) { // 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; editorBeatmap.Add(new HitCircle { StartTime = time, Position = position, NewCombo = i == 0 && HitObject.NewCombo, SampleControlPoint = samplePoint, Samples = HitObject.HeadCircle.Samples.Select(s => s.With()).ToList() }); i += 1; time = HitObject.StartTime + i * streamSpacing; } editorBeatmap.Remove(HitObject); changeHandler.EndChange(); }