Example #1
0
        private void addPathData(TextWriter writer, IHasPath pathData, Vector2 position)
        {
            PathType?lastType = null;

            for (int i = 0; i < pathData.Path.ControlPoints.Count; i++)
            {
                PathControlPoint point = pathData.Path.ControlPoints[i];

                if (point.Type != null)
                {
                    // We've reached a new (explicit) segment!

                    // Explicit segments have a new format in which the type is injected into the middle of the control point string.
                    // To preserve compatibility with osu-stable as much as possible, explicit segments with the same type are converted to use implicit segments by duplicating the control point.
                    // One exception are consecutive perfect curves, which aren't supported in osu!stable and can lead to decoding issues if encoded as implicit segments
                    bool needsExplicitSegment = point.Type != lastType || point.Type == PathType.PerfectCurve;

                    // Another exception to this is when the last two control points of the last segment were duplicated. This is not a scenario supported by osu!stable.
                    // Lazer does not add implicit segments for the last two control points of _any_ explicit segment, so an explicit segment is forced in order to maintain consistency with the decoder.
                    if (i > 1)
                    {
                        // We need to use the absolute control point position to determine equality, otherwise floating point issues may arise.
                        Vector2 p1 = position + pathData.Path.ControlPoints[i - 1].Position;
                        Vector2 p2 = position + pathData.Path.ControlPoints[i - 2].Position;

                        if ((int)p1.X == (int)p2.X && (int)p1.Y == (int)p2.Y)
                        {
                            needsExplicitSegment = true;
                        }
                    }

                    if (needsExplicitSegment)
                    {
                        switch (point.Type)
                        {
                        case PathType.Bezier:
                            writer.Write("B|");
                            break;

                        case PathType.Catmull:
                            writer.Write("C|");
                            break;

                        case PathType.PerfectCurve:
                            writer.Write("P|");
                            break;

                        case PathType.Linear:
                            writer.Write("L|");
                            break;
                        }

                        lastType = point.Type;
                    }
                    else
                    {
                        // New segment with the same type - duplicate the control point
                        writer.Write(FormattableString.Invariant($"{position.X + point.Position.X}:{position.Y + point.Position.Y}|"));
                    }
                }

                if (i != 0)
                {
                    writer.Write(FormattableString.Invariant($"{position.X + point.Position.X}:{position.Y + point.Position.Y}"));
                    writer.Write(i != pathData.Path.ControlPoints.Count - 1 ? "|" : ",");
                }
            }

            var curveData = pathData as IHasPathWithRepeats;

            writer.Write(FormattableString.Invariant($"{(curveData?.RepeatCount ?? 0) + 1},"));
            writer.Write(FormattableString.Invariant($"{pathData.Path.Distance},"));

            if (curveData != null)
            {
                for (int i = 0; i < curveData.NodeSamples.Count; i++)
                {
                    writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}"));
                    writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
                }

                for (int i = 0; i < curveData.NodeSamples.Count; i++)
                {
                    writer.Write(getSampleBank(curveData.NodeSamples[i], true));
                    writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
                }
            }
        }
Example #2
0
        private void addPathData(TextWriter writer, IHasPath pathData, Vector2 position)
        {
            PathType?lastType = null;

            for (int i = 0; i < pathData.Path.ControlPoints.Count; i++)
            {
                PathControlPoint point = pathData.Path.ControlPoints[i];

                if (point.Type.Value != null)
                {
                    if (point.Type.Value != lastType)
                    {
                        switch (point.Type.Value)
                        {
                        case PathType.Bezier:
                            writer.Write("B|");
                            break;

                        case PathType.Catmull:
                            writer.Write("C|");
                            break;

                        case PathType.PerfectCurve:
                            writer.Write("P|");
                            break;

                        case PathType.Linear:
                            writer.Write("L|");
                            break;
                        }

                        lastType = point.Type.Value;
                    }
                    else
                    {
                        // New segment with the same type - duplicate the control point
                        writer.Write(FormattableString.Invariant($"{position.X + point.Position.Value.X}:{position.Y + point.Position.Value.Y}|"));
                    }
                }

                if (i != 0)
                {
                    writer.Write(FormattableString.Invariant($"{position.X + point.Position.Value.X}:{position.Y + point.Position.Value.Y}"));
                    writer.Write(i != pathData.Path.ControlPoints.Count - 1 ? "|" : ",");
                }
            }

            var curveData = pathData as IHasPathWithRepeats;

            writer.Write(FormattableString.Invariant($"{(curveData?.RepeatCount ?? 0) + 1},"));
            writer.Write(FormattableString.Invariant($"{pathData.Path.Distance},"));

            if (curveData != null)
            {
                for (int i = 0; i < curveData.NodeSamples.Count; i++)
                {
                    writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}"));
                    writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
                }

                for (int i = 0; i < curveData.NodeSamples.Count; i++)
                {
                    writer.Write(getSampleBank(curveData.NodeSamples[i], true));
                    writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
                }
            }
        }