/// <summary> /// Parses notes data /// </summary> private void ParseNote(Pattern pattern, string noteType, string noteData) { Note note; string[] commaSplit; string[] lineSplit; string[] colonSplit; float time; int column; // For now, note types are single characters, may change if necessary in future if (noteType.Length != 1) { this.Warning("Unrecognized note type"); return; } // Get the first time, because its used by everyone colonSplit = noteData.Split(':'); if (colonSplit.Length < 2) { goto ParseWarning; } time = this.ParseFloat("note time", colonSplit[0], false); if (time == -1f) { goto ParseWarning; } // Parse based on note type NoteType type = this.ParseNoteType(noteType[0]); switch (type) { // MINE: 0=time:column,column,column,... case NoteType.MINE: // TAP: 1=time:column,column,column,... case NoteType.TAP: // Note columns commaSplit = noteData.Split(','); foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) { goto ParseWarning; } note = new Note(); note.type = type; note.AddPoint(time, column); this.AddNote(pattern, note); } break; // HOLD: 2=time:column,column,column,... case NoteType.HOLD: // ROLL: 3=time:column,column,column,...|time case NoteType.ROLL: // Note end time lineSplit = colonSplit[1].Split('|'); if (lineSplit.Length != 2) { goto ParseWarning; } float endTime = this.ParseFloat(type + " note end time", lineSplit[1], false); if (endTime == -1f) { goto ParseWarning; } // Columns commaSplit = colonSplit[0].Split(','); foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) { goto ParseWarning; } note = new Note(); note.type = type; note.AddPoint(time, column); note.AddPoint(endTime, column); this.AddNote(pattern, note); } break; // REPEAT: 4=time:column,column,column,...|time|time|time|... case NoteType.REPEAT: List <float> times = new List <float>(); List <int> columns = new List <int>(); // Note start time times.Add(time); // Time split lineSplit = noteData.Split('|'); if (lineSplit.Length < 2) { goto ParseWarning; } for (int i = 1; i < lineSplit.Length; i++) { time = this.ParseFloat(type + " note time", lineSplit[i], false); if (time == -1f) { goto ParseWarning; } times.Add(time); } // Column commaSplit = lineSplit[0].Split(','); if (commaSplit.Length < 1) { goto ParseWarning; } foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) { goto ParseWarning; } columns.Add(column); } // Add notes foreach (int c in columns) { note = new Note(); note.type = type; foreach (int t in times) { note.AddPoint(t, c); } this.AddNote(pattern, note); } break; // SLIDE: 5=time:column|time:column|time:column|... case NoteType.SLIDE: // Only one Note per Slide line note = new Note(); note.type = type; // Split into time:column pairs lineSplit = noteData.Split('|'); if (lineSplit.Length < 2) { goto ParseWarning; } // Parse each pair foreach (string s in lineSplit) { colonSplit = s.Split(':'); if (colonSplit.Length != 2) { goto ParseWarning; } time = this.ParseFloat(type + " note time", colonSplit[0], false); if (time == -1f) { goto ParseWarning; } column = this.ParseInt(type + " note column", colonSplit[1], false); if (column == -1f) { goto ParseWarning; } note.AddPoint(time, column); } // Add the note this.AddNote(pattern, note); break; // LABEL: L=time:text case NoteType.LABEL: string text = colonSplit[1]; note = new Note(); note.type = NoteType.LABEL; note.eventTime = time; note.eventStringVal = text; this.AddNote(pattern, note); break; // BG: G=time:index case NoteType.BG: int backgroundIndex = this.ParseInt("Background index", colonSplit[1], false); if (backgroundIndex == -1) { goto ParseWarning; } note = new Note(); note.type = NoteType.BG; note.eventTime = time; note.eventIntVal = backgroundIndex; this.AddNote(pattern, note); break; // BPM: B=time:value case NoteType.BPM: float bpm = this.ParseFloat("BPM change value", colonSplit[1], false); if (bpm == -1f) { goto ParseWarning; } note = new Note(); note.type = NoteType.BPM; note.eventTime = time; note.eventFloatVal = bpm; this.AddNote(pattern, note); break; // STOP: S=time:duration case NoteType.STOP: float duration = this.ParseFloat("Stop duration value", colonSplit[1], false); if (duration == -1f) { goto ParseWarning; } note = new Note(); note.type = NoteType.STOP; note.eventTime = time; note.eventFloatVal = duration; this.AddNote(pattern, note); break; default: goto ParseWarning; } // Generic warning, out of laziness ParseWarning: Warning("Improperly formatted line"); }
/// <summary> /// Parses notes data /// </summary> private void ParseNote(Pattern pattern, string noteType, string noteData) { Note note; string[] commaSplit; string[] lineSplit; string[] colonSplit; float time; int column; // For now, note types are single characters, may change if necessary in future if (noteType.Length != 1) { this.Warning("Unrecognized note type"); return; } // Get the first time, because its used by everyone colonSplit = noteData.Split(':'); if (colonSplit.Length < 2) goto ParseWarning; time = this.ParseFloat("note time", colonSplit[0], false); if (time == -1f) goto ParseWarning; // Parse based on note type NoteType type = this.ParseNoteType(noteType[0]); switch (type) { // MINE: 0=time:column,column,column,... case NoteType.MINE: // TAP: 1=time:column,column,column,... case NoteType.TAP: // Note columns commaSplit = noteData.Split(','); foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) goto ParseWarning; note = new Note(); note.type = type; note.AddPoint(time, column); this.AddNote(pattern, note); } break; // HOLD: 2=time:column,column,column,... case NoteType.HOLD: // ROLL: 3=time:column,column,column,...|time case NoteType.ROLL: // Note end time lineSplit = colonSplit[1].Split('|'); if (lineSplit.Length != 2) goto ParseWarning; float endTime = this.ParseFloat(type + " note end time", lineSplit[1], false); if (endTime == -1f) goto ParseWarning; // Columns commaSplit = colonSplit[0].Split(','); foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) goto ParseWarning; note = new Note(); note.type = type; note.AddPoint(time, column); note.AddPoint(endTime, column); this.AddNote(pattern, note); } break; // REPEAT: 4=time:column,column,column,...|time|time|time|... case NoteType.REPEAT: List<float> times = new List<float>(); List<int> columns = new List<int>(); // Note start time times.Add(time); // Time split lineSplit = noteData.Split('|'); if (lineSplit.Length < 2) goto ParseWarning; for (int i = 1; i < lineSplit.Length; i++) { time = this.ParseFloat(type + " note time", lineSplit[i], false); if (time == -1f) goto ParseWarning; times.Add(time); } // Column commaSplit = lineSplit[0].Split(','); if (commaSplit.Length < 1) goto ParseWarning; foreach (string s in commaSplit) { column = this.ParseInt(type + " note column", s, false); if (column == -1) goto ParseWarning; columns.Add(column); } // Add notes foreach (int c in columns) { note = new Note(); note.type = type; foreach (int t in times) { note.AddPoint(t, c); } this.AddNote(pattern, note); } break; // SLIDE: 5=time:column|time:column|time:column|... case NoteType.SLIDE: // Only one Note per Slide line note = new Note(); note.type = type; // Split into time:column pairs lineSplit = noteData.Split('|'); if (lineSplit.Length < 2) goto ParseWarning; // Parse each pair foreach (string s in lineSplit) { colonSplit = s.Split(':'); if (colonSplit.Length != 2) goto ParseWarning; time = this.ParseFloat(type + " note time", colonSplit[0], false); if (time == -1f) goto ParseWarning; column = this.ParseInt(type + " note column", colonSplit[1], false); if (column == -1f) goto ParseWarning; note.AddPoint(time, column); } // Add the note this.AddNote(pattern, note); break; // LABEL: L=time:text case NoteType.LABEL: string text = colonSplit[1]; note = new Note(); note.type = NoteType.LABEL; note.eventTime = time; note.eventStringVal = text; this.AddNote(pattern, note); break; // BG: G=time:index case NoteType.BG: int backgroundIndex = this.ParseInt("Background index", colonSplit[1], false); if (backgroundIndex == -1) goto ParseWarning; note = new Note(); note.type = NoteType.BG; note.eventTime = time; note.eventIntVal = backgroundIndex; this.AddNote(pattern, note); break; // BPM: B=time:value case NoteType.BPM: float bpm = this.ParseFloat("BPM change value", colonSplit[1], false); if (bpm == -1f) goto ParseWarning; note = new Note(); note.type = NoteType.BPM; note.eventTime = time; note.eventFloatVal = bpm; this.AddNote(pattern, note); break; // STOP: S=time:duration case NoteType.STOP: float duration = this.ParseFloat("Stop duration value", colonSplit[1], false); if (duration == -1f) goto ParseWarning; note = new Note(); note.type = NoteType.STOP; note.eventTime = time; note.eventFloatVal = duration; this.AddNote(pattern, note); break; default: goto ParseWarning; } // Generic warning, out of laziness ParseWarning: Warning("Improperly formatted line"); }
/// <summary> /// Parses notes data /// </summary> private void ParseMeasure(Pattern pattern, float beatStart, List <string> measure) { // Amount of beat increase per line // Note that in StepMania, the beat fraction is important note data for // determining the note colour. // In Beats2, to standardize things, we ignore beat fraction // (it also gives an unequal timing compared to other modes) float beatFraction = (float)BEATS_PER_MEASURE / (float)measure.Count; NoteType type; Note note; float beat = 0f; float time; string line; // Down each line for (int i = 0; i < measure.Count; i++) { line = measure[i]; beat += beatFraction; time = this.CalculateTime(beat); // Across each line, width should match the key count for (int column = 0; column < pattern.keyCount; column++) { type = this.ParseNoteType(line[column]); switch (type) { case NoteType.MINE: case NoteType.TAP: note = new Note(); note.type = type; note.AddPoint(time, column); this.AddNote(pattern, note); break; case NoteType.HOLD: case NoteType.ROLL: note = new Note(); note.type = type; note.AddPoint(time, column); // Queue the note and wait for end if (_holdQueue[column] != null) { this.Warning("Hold queue already contains a note, dropping previous note"); } _holdQueue[column] = note; break; case NoteType.SLIDE: // Hold/Roll end if ((note = _holdQueue[column]) != null) { note.AddPoint(time, column); this.AddNote(pattern, note); _holdQueue[column] = null; } else { this.Warning("Hold end note with no initial starting head"); } break; default: // Don't do a warning because empties also go here break; } } } }