private void handleEvent(string line) { string[] split = line.Split(','); EventType type; if (!Enum.TryParse(split[0], out type)) { throw new InvalidDataException($@"Unknown event type: {split[0]}"); } switch (type) { case EventType.Background: string bgFilename = split[2].Trim('"'); beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename); break; case EventType.Video: string videoFilename = split[2].Trim('"'); beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename); break; case EventType.Break: double start = getOffsetTime(Parsing.ParseDouble(split[1])); var breakEvent = new BreakPeriod { StartTime = start, EndTime = Math.Max(start, getOffsetTime(Parsing.ParseDouble(split[2]))) }; if (!breakEvent.HasEffect) { return; } beatmap.Breaks.Add(breakEvent); break; } }
private void handleDifficulty(string line) { var pair = SplitKeyVal(line); var difficulty = beatmap.Difficulty; switch (pair.Key) { case @"HPDrainRate": difficulty.DrainRate = Parsing.ParseFloat(pair.Value); break; case @"CircleSize": difficulty.CircleSize = Parsing.ParseFloat(pair.Value); break; case @"OverallDifficulty": difficulty.OverallDifficulty = Parsing.ParseFloat(pair.Value); if (!hasApproachRate) { difficulty.ApproachRate = difficulty.OverallDifficulty; } break; case @"ApproachRate": difficulty.ApproachRate = Parsing.ParseFloat(pair.Value); hasApproachRate = true; break; case @"SliderMultiplier": difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": difficulty.SliderTickRate = Parsing.ParseDouble(pair.Value); break; } }
private void handleEvent(string line) { string[] split = line.Split(','); if (!Enum.TryParse(split[0], out LegacyEventType type)) { throw new InvalidDataException($@"Unknown event type: {split[0]}"); } switch (type) { case LegacyEventType.Background: beatmap.BeatmapInfo.Metadata.BackgroundFile = CleanFilename(split[2]); break; case LegacyEventType.Break: double start = getOffsetTime(Parsing.ParseDouble(split[1])); double end = Math.Max(start, getOffsetTime(Parsing.ParseDouble(split[2]))); beatmap.Breaks.Add(new BreakPeriod(start, end)); break; } }
private void handleTimingPoint(string line) { string[] split = line.Split(','); double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); double beatLength = Parsing.ParseDouble(split[1].Trim()); double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; if (split.Length >= 3) { timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); } LegacySampleBank sampleSet = defaultSampleBank; if (split.Length >= 4) { sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); } int customSampleBank = 0; if (split.Length >= 5) { customSampleBank = Parsing.ParseInt(split[4]); } int sampleVolume = defaultSampleVolume; if (split.Length >= 6) { sampleVolume = Parsing.ParseInt(split[5]); } bool timingChange = true; if (split.Length >= 7) { timingChange = split[6][0] == '1'; } bool kiaiMode = false; bool omitFirstBarSignature = false; if (split.Length >= 8) { LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]); kiaiMode = effectFlags.HasFlag(LegacyEffectFlags.Kiai); omitFirstBarSignature = effectFlags.HasFlag(LegacyEffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") { stringSampleSet = @"normal"; } if (timingChange) { var controlPoint = CreateTimingControlPoint(); controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; addControlPoint(time, controlPoint, true); } #pragma warning disable 618 addControlPoint(time, new LegacyDifficultyControlPoint(beatLength) #pragma warning restore 618 { SpeedMultiplier = speedMultiplier, }, timingChange); addControlPoint(time, new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, }, timingChange); addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, }, timingChange); }
public static void Register() { AddDecoder <Beatmap>(@"osu file format v", m => new LegacyBeatmapDecoder(Parsing.ParseInt(m.Split('v').Last()))); SetFallbackDecoder <Beatmap>(() => new LegacyBeatmapDecoder()); }
private void handleGeneral(string line) { var pair = SplitKeyVal(line); var metadata = beatmap.BeatmapInfo.Metadata; switch (pair.Key) { case @"AudioFilename": metadata.AudioFile = pair.Value.ToStandardisedPath(); break; case @"AudioLeadIn": beatmap.BeatmapInfo.AudioLeadIn = Parsing.ParseInt(pair.Value); break; case @"PreviewTime": metadata.PreviewTime = getOffsetTime(Parsing.ParseInt(pair.Value)); break; case @"Countdown": beatmap.BeatmapInfo.Countdown = Parsing.ParseInt(pair.Value) == 1; break; case @"SampleSet": defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); break; case @"SampleVolume": defaultSampleVolume = Parsing.ParseInt(pair.Value); break; case @"StackLeniency": beatmap.BeatmapInfo.StackLeniency = Parsing.ParseFloat(pair.Value); break; case @"Mode": beatmap.BeatmapInfo.RulesetID = Parsing.ParseInt(pair.Value); switch (beatmap.BeatmapInfo.RulesetID) { case 0: parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 1: parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 2: parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 3: parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; } break; case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = Parsing.ParseInt(pair.Value) == 1; break; case @"SpecialStyle": beatmap.BeatmapInfo.SpecialStyle = Parsing.ParseInt(pair.Value) == 1; break; case @"WidescreenStoryboard": beatmap.BeatmapInfo.WidescreenStoryboard = Parsing.ParseInt(pair.Value) == 1; break; } }
private void handleTimingPoint(string line) { string[] split = line.Split(','); double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); double beatLength = Parsing.ParseDouble(split[1].Trim()); double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignature timeSignature = TimeSignature.SimpleQuadruple; if (split.Length >= 3) { timeSignature = split[2][0] == '0' ? TimeSignature.SimpleQuadruple : new TimeSignature(Parsing.ParseInt(split[2])); } LegacySampleBank sampleSet = defaultSampleBank; if (split.Length >= 4) { sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); } int customSampleBank = 0; if (split.Length >= 5) { customSampleBank = Parsing.ParseInt(split[4]); } int sampleVolume = defaultSampleVolume; if (split.Length >= 6) { sampleVolume = Parsing.ParseInt(split[5]); } bool timingChange = true; if (split.Length >= 7) { timingChange = split[6][0] == '1'; } bool kiaiMode = false; bool omitFirstBarSignature = false; if (split.Length >= 8) { LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]); kiaiMode = effectFlags.HasFlagFast(LegacyEffectFlags.Kiai); omitFirstBarSignature = effectFlags.HasFlagFast(LegacyEffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") { stringSampleSet = @"normal"; } if (timingChange) { var controlPoint = CreateTimingControlPoint(); controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; addControlPoint(time, controlPoint, true); } #pragma warning disable 618 addControlPoint(time, new LegacyDifficultyControlPoint(beatLength) #pragma warning restore 618 { SliderVelocity = speedMultiplier, }, timingChange); var effectPoint = new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, }; bool isOsuRuleset = beatmap.BeatmapInfo.Ruleset.OnlineID == 0; // scrolling rulesets use effect points rather than difficulty points for scroll speed adjustments. if (!isOsuRuleset) { effectPoint.ScrollSpeed = speedMultiplier; } addControlPoint(time, effectPoint, timingChange); addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, }, timingChange); }
private void handleEvents(string line) { var depth = 0; foreach (char c in line) { if (c == ' ' || c == '_') { depth++; } else { break; } } line = line.Substring(depth); decodeVariables(ref line); string[] split = line.Split(','); if (depth == 0) { storyboardSprite = null; if (!Enum.TryParse(split[0], out LegacyEventType type)) { throw new InvalidDataException($@"Unknown event type: {split[0]}"); } switch (type) { case LegacyEventType.Video: { var offset = Parsing.ParseInt(split[1]); var path = CleanFilename(split[2]); storyboard.GetLayer("Video").Add(new StoryboardVideo(path, offset)); break; } case LegacyEventType.Sprite: { var layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); var path = CleanFilename(split[3]); var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); storyboard.GetLayer(layer).Add(storyboardSprite); break; } case LegacyEventType.Animation: { var layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); var path = CleanFilename(split[3]); var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); var frameCount = Parsing.ParseInt(split[6]); var frameDelay = Parsing.ParseDouble(split[7]); if (FormatVersion < 6) { // this is random as hell but taken straight from osu-stable. frameDelay = Math.Round(0.015 * frameDelay) * 1.186 * (1000 / 60f); } var loopType = split.Length > 8 ? parseAnimationLoopType(split[8]) : AnimationLoopType.LoopForever; storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); storyboard.GetLayer(layer).Add(storyboardSprite); break; } case LegacyEventType.Sample: { var time = Parsing.ParseDouble(split[1]); var layer = parseLayer(split[2]); var path = CleanFilename(split[3]); var volume = split.Length > 4 ? Parsing.ParseFloat(split[4]) : 100; storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume)); break; } } } else { if (depth < 2) { timelineGroup = storyboardSprite?.TimelineGroup; } var commandType = split[0]; switch (commandType) { case "T": { var triggerName = split[1]; var startTime = split.Length > 2 ? Parsing.ParseDouble(split[2]) : double.MinValue; var endTime = split.Length > 3 ? Parsing.ParseDouble(split[3]) : double.MaxValue; var groupNumber = split.Length > 4 ? Parsing.ParseInt(split[4]) : 0; timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); break; } case "L": { var startTime = Parsing.ParseDouble(split[1]); var loopCount = Parsing.ParseInt(split[2]); timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); break; } default: { if (string.IsNullOrEmpty(split[3])) { split[3] = split[2]; } var easing = (Easing)Parsing.ParseInt(split[1]); var startTime = Parsing.ParseDouble(split[2]); var endTime = Parsing.ParseDouble(split[3]); switch (commandType) { case "F": { var startValue = Parsing.ParseFloat(split[4]); var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); break; } case "S": { var startValue = Parsing.ParseFloat(split[4]); var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue); break; } case "V": { var startX = Parsing.ParseFloat(split[4]); var startY = Parsing.ParseFloat(split[5]); var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); break; } case "R": { var startValue = Parsing.ParseFloat(split[4]); var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathUtils.RadiansToDegrees(startValue), MathUtils.RadiansToDegrees(endValue)); break; } case "M": { var startX = Parsing.ParseFloat(split[4]); var startY = Parsing.ParseFloat(split[5]); var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); break; } case "MX": { var startValue = Parsing.ParseFloat(split[4]); var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); break; } case "MY": { var startValue = Parsing.ParseFloat(split[4]); var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); break; } case "C": { var startRed = Parsing.ParseFloat(split[4]); var startGreen = Parsing.ParseFloat(split[5]); var startBlue = Parsing.ParseFloat(split[6]); var endRed = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startRed; var endGreen = split.Length > 8 ? Parsing.ParseFloat(split[8]) : startGreen; var endBlue = split.Length > 9 ? Parsing.ParseFloat(split[9]) : startBlue; timelineGroup?.Colour.Add(easing, startTime, endTime, new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); break; } case "P": { var type = split[4]; switch (type) { case "A": timelineGroup?.BlendingParameters.Add(easing, startTime, endTime, BlendingParameters.Additive, startTime == endTime ? BlendingParameters.Additive : BlendingParameters.Inherit); break; case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break; case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } break; } default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } break; } } } }
public static void Register() { // note that this isn't completely correct AddDecoder <Storyboard>(@"osu file format v", m => new LegacyStoryboardDecoder(Parsing.ParseInt(m.Split('v').Last()))); AddDecoder <Storyboard>(@"[Events]", m => new LegacyStoryboardDecoder()); SetFallbackDecoder <Storyboard>(() => new LegacyStoryboardDecoder()); }
private void handleGeneral(string line) { var pair = SplitKeyVal(line); var metadata = beatmap.BeatmapInfo.Metadata; switch (pair.Key) { case @"AudioFilename": metadata.AudioFile = pair.Value.ToStandardisedPath(); break; case @"AudioLeadIn": beatmap.BeatmapInfo.AudioLeadIn = Parsing.ParseInt(pair.Value); break; case @"PreviewTime": metadata.PreviewTime = getOffsetTime(Parsing.ParseInt(pair.Value)); break; case @"SampleSet": defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); break; case @"SampleVolume": defaultSampleVolume = Parsing.ParseInt(pair.Value); break; case @"StackLeniency": beatmap.BeatmapInfo.StackLeniency = Parsing.ParseFloat(pair.Value); break; case @"Mode": int rulesetID = Parsing.ParseInt(pair.Value); beatmap.BeatmapInfo.Ruleset = RulesetStore.GetRuleset(rulesetID) ?? throw new ArgumentException("Ruleset is not available locally."); switch (rulesetID) { case 0: parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 1: parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 2: parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 3: parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; } break; case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = Parsing.ParseInt(pair.Value) == 1; break; case @"SpecialStyle": beatmap.BeatmapInfo.SpecialStyle = Parsing.ParseInt(pair.Value) == 1; break; case @"WidescreenStoryboard": beatmap.BeatmapInfo.WidescreenStoryboard = Parsing.ParseInt(pair.Value) == 1; break; case @"EpilepsyWarning": beatmap.BeatmapInfo.EpilepsyWarning = Parsing.ParseInt(pair.Value) == 1; break; case @"SamplesMatchPlaybackRate": beatmap.BeatmapInfo.SamplesMatchPlaybackRate = Parsing.ParseInt(pair.Value) == 1; break; case @"Countdown": beatmap.BeatmapInfo.Countdown = (CountdownType)Enum.Parse(typeof(CountdownType), pair.Value); break; case @"CountdownOffset": beatmap.BeatmapInfo.CountdownOffset = Parsing.ParseInt(pair.Value); break; } }
private void handleTimingPoint(string line) { string[] split = line.Split(','); double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); double beatLength = Parsing.ParseDouble(split[1].Trim()); double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; if (split.Length >= 3) { timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); } LegacySampleBank sampleSet = defaultSampleBank; if (split.Length >= 4) { sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); } int customSampleBank = 0; if (split.Length >= 5) { customSampleBank = Parsing.ParseInt(split[4]); } int sampleVolume = defaultSampleVolume; if (split.Length >= 6) { sampleVolume = Parsing.ParseInt(split[5]); } bool timingChange = true; if (split.Length >= 7) { timingChange = split[6][0] == '1'; } bool kiaiMode = false; bool omitFirstBarSignature = false; if (split.Length >= 8) { EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") { stringSampleSet = @"normal"; } if (timingChange) { var controlPoint = CreateTimingControlPoint(); controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; addControlPoint(time, controlPoint, true); } addControlPoint(time, new LegacyDifficultyControlPoint { SpeedMultiplier = speedMultiplier, }, timingChange); addControlPoint(time, new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, }, timingChange); addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, }, timingChange); // To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but // appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line // with the same time value (allowing them to overwrite as necessary). // // The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal. if (timingChange) { flushPendingPoints(); } }
private void handleTimingPoint(string line) { try { string[] split = line.Split(','); double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); double beatLength = Parsing.ParseDouble(split[1].Trim()); double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; if (split.Length >= 3) { timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); } LegacySampleBank sampleSet = defaultSampleBank; if (split.Length >= 4) { sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); } int customSampleBank = 0; if (split.Length >= 5) { customSampleBank = Parsing.ParseInt(split[4]); } int sampleVolume = defaultSampleVolume; if (split.Length >= 6) { sampleVolume = Parsing.ParseInt(split[5]); } bool timingChange = true; if (split.Length >= 7) { timingChange = split[6][0] == '1'; } bool kiaiMode = false; bool omitFirstBarSignature = false; if (split.Length >= 8) { EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") { stringSampleSet = @"normal"; } if (timingChange) { var controlPoint = CreateTimingControlPoint(); controlPoint.Time = time; controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; handleTimingControlPoint(controlPoint); } handleDifficultyControlPoint(new DifficultyControlPoint { Time = time, SpeedMultiplier = speedMultiplier, AutoGenerated = timingChange }); handleEffectControlPoint(new EffectControlPoint { Time = time, KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, AutoGenerated = timingChange }); handleSampleControlPoint(new LegacySampleControlPoint { Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, AutoGenerated = timingChange }); } catch (FormatException) { Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); } catch (OverflowException) { Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); } }