private static void CalculateGroupID(Note note, CompiledNote compiledNote) { if (note.GroupID != EntityID.Invalid) { compiledNote.GroupID = note.GroupID; } else { int groupID; FlickGroupModificationResult result; Note groupStart; if (!note.TryGetFlickGroupID(out result, out groupID, out groupStart)) { // No need to set a group ID. E.g. the note is not a flick / slide note. return; } switch (result) { case FlickGroupModificationResult.Reused: note.GroupID = compiledNote.GroupID = groupID; break; case FlickGroupModificationResult.CreationPending: groupID = FlickGroupIDGenerator.Next(); groupStart.GroupID = note.GroupID = compiledNote.GroupID = groupID; break; } } }
private static DelesteNoteType TranslateNoteType(CompiledNote note) { switch (note.Type) { case NoteType.TapOrFlick: switch (note.FlickType) { case (int)NoteFlickType.Tap: return(DelesteNoteType.Tap); case (int)NoteFlickType.FlickLeft: return(DelesteNoteType.FlickLeft); case (int)NoteFlickType.FlickRight: return(DelesteNoteType.FlickRight); default: // Should have thrown an exception. return(DelesteNoteType.Tap); } case NoteType.Hold: return(DelesteNoteType.Hold); case NoteType.Slide: return(DelesteNoteType.Slide); default: throw new ArgumentOutOfRangeException(); } }
private static void SetCommonNoteProperties(Note note, CompiledNote compiledNote) { compiledNote.Type = note.Type; compiledNote.StartPosition = note.StartPosition; compiledNote.FinishPosition = note.FinishPosition; compiledNote.FlickType = (int)note.FlickType; compiledNote.IsSync = note.IsSync; }
public static void CompileTo(this Score score, CompiledScore compiledScore) { FlickGroupIDGenerator.Reset(); var compiledNotes = compiledScore.Notes; compiledNotes.Clear(); // Clear the GroupID caches. foreach (var bar in score.Bars) { foreach (var note in bar.Notes) { note.GroupID = EntityID.Invalid; var compiledNote = new CompiledNote(); SetCommonNoteProperties(note, compiledNote); CalculateGroupID(note, compiledNote); compiledNote.HitTiming = note.HitTiming; compiledNotes.Add(compiledNote); } } // The normal gaming notes. var noteId = 3; foreach (var compiledNote in compiledNotes) { compiledNote.ID = noteId++; } // Special notes are added to their destined positions. var totalNoteCount = compiledNotes.Count; var scoreInfoNote = new CompiledNote { ID = 1, Type = NoteType.NoteCount, FlickType = totalNoteCount }; var songStartNote = new CompiledNote { ID = 2, Type = NoteType.MusicStart }; compiledNotes.Insert(0, scoreInfoNote); compiledNotes.Insert(1, songStartNote); double endTiming; if (score.Bars.Count > 0) { var lastBar = score.Bars.Last(); endTiming = lastBar.StartTime + lastBar.TimeLength; } else { endTiming = 0; } var songEndNote = new CompiledNote { ID = noteId, Type = NoteType.MusicEnd, HitTiming = endTiming }; compiledNotes.Add(songEndNote); }
private static CompiledScore Compile([NotNull] Score score, [CanBeNull] TimeSpan?userDefinedEnding) { var notes = score.GetAllNotes(); // First, calculate all timing at the grid lines. var allBpmNotes = notes.Where(n => n.Basic.Type == NoteType.VariantBpm).ToArray(); var timings = new Dictionary <Bar, double[]>(); var currentTiming = score.Project.Settings.StartTimeOffset; var currentBpm = score.Project.Settings.BeatPerMinute; var currentInterval = BeatmapMathHelper.BpmToInterval(currentBpm); foreach (var bar in score.Bars) { var currentGridPerSignature = bar.GetGridPerSignature(); var numGrids = bar.GetNumberOfGrids(); var t = new double[numGrids]; if (allBpmNotes.Any(n => n.Basic.Bar == bar)) { // If there are variant BPM notes, we have to do some math... var bpmNotesInThisBar = allBpmNotes.Where(n => n.Basic.Bar == bar).ToList(); bpmNotesInThisBar.Sort((n1, n2) => n1.Basic.IndexInGrid.CompareTo(n2.Basic.IndexInGrid)); var bpmNoteIndex = 0; for (var i = 0; i < numGrids; ++i) { if (bpmNoteIndex < bpmNotesInThisBar.Count) { var bpmNote = bpmNotesInThisBar[bpmNoteIndex]; if (i == bpmNote.Basic.IndexInGrid) { Debug.Assert(bpmNote.Params != null, "bpmNote.Params != null"); // Yes! We have a visitor: a variant BPM note! currentBpm = bpmNote.Params.NewBpm; currentInterval = BeatmapMathHelper.BpmToInterval(currentBpm); ++bpmNoteIndex; } } t[i] = currentTiming; currentTiming += currentInterval / currentGridPerSignature; } } else { // If there are no variant BPM notes, things get a lot easier. for (var i = 0; i < numGrids; ++i) { t[i] = currentTiming + currentInterval * i / currentGridPerSignature; } var currentSignature = bar.GetSignature(); currentTiming += currentInterval * currentSignature; } timings[bar] = t; } // Then, create a list and fill in basic information. var compiledNotes = new List <CompiledNote>(); var noteMap1 = new Dictionary <CompiledNote, Note>(); var noteMap2 = new Dictionary <Note, CompiledNote>(); foreach (var note in notes) { if (!note.Helper.IsGaming) { continue; } var compiledNote = new CompiledNote(); compiledNote.Type = note.Basic.Type; compiledNote.HitTiming = timings[note.Basic.Bar][note.Basic.IndexInGrid]; compiledNote.StartPosition = note.Basic.StartPosition; compiledNote.FinishPosition = note.Basic.FinishPosition; compiledNote.FlickType = note.Basic.FlickType; compiledNote.IsSync = note.Helper.IsSync; compiledNotes.Add(compiledNote); noteMap1[compiledNote] = note; noteMap2[note] = compiledNote; } compiledNotes.Sort((n1, n2) => n1.HitTiming.CompareTo(n2.HitTiming)); // ReSharper disable once InconsistentNaming // Then, calculate group IDs. var currentGroupID = 1; foreach (var compiledNote in compiledNotes) { if (compiledNote.GroupID != 0) { continue; } var note = noteMap1[compiledNote]; if (!note.Helper.IsFlick && !note.Helper.IsSlide) { continue; } var cn = compiledNote; if (note.Helper.IsFlick) { var n = note; while (n != null) { cn.GroupID = currentGroupID; n = n.Editor.NextFlick; if (n != null) { cn = noteMap2[n]; } } ++currentGroupID; } else if (note.Helper.IsSlide) { var n = note; var n2 = n; while (n != null) { cn.GroupID = currentGroupID; n2 = n; n = n.Editor.NextSlide; if (n != null) { cn = noteMap2[n]; } } // A slide group, directly followed by a flick group. if (n2.Helper.HasNextFlick) { n = n2.Editor.NextFlick; while (n != null) { cn = noteMap2[n]; cn.GroupID = currentGroupID; n = n.Editor.NextFlick; } } ++currentGroupID; } } // Then, add three key notes. (Keynotes, hahaha.) var totalNoteCount = compiledNotes.Count; var scoreInfoNote = new CompiledNote(); scoreInfoNote.Type = NoteType.NoteCount; // Here I used a trick. This will run well while violating the meaning of enum. scoreInfoNote.FlickType = (NoteFlickType)totalNoteCount; var songStartNote = new CompiledNote { Type = NoteType.MusicStart }; var endTiming = userDefinedEnding?.TotalSeconds ?? currentTiming; var songEndNote = new CompiledNote { Type = NoteType.MusicEnd, HitTiming = endTiming }; compiledNotes.Insert(0, scoreInfoNote); compiledNotes.Insert(1, songStartNote); compiledNotes.Add(songEndNote); // ReSharper disable once InconsistentNaming // Finally, ID them. var currentNoteID = 1; foreach (var note in compiledNotes) { note.ID = currentNoteID; ++currentNoteID; } // We did it! Oh yeah! var compiledScore = new CompiledScore(compiledNotes); return(compiledScore); }