public static CompiledScore Compile(this Score score) { var compiledScore = new CompiledScore(); CompileTo(score, compiledScore); return(compiledScore); }
public static string GetCsvString([NotNull] this CompiledScore score) { var sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { var config = new Configuration(); config.RegisterClassMap <ScoreCsvMap>(); config.HasHeaderRecord = true; config.TrimOptions = TrimOptions.None; using (var csv = new CsvWriter(writer, config)) { var newList = new List <CompiledNote>(score.Notes); csv.WriteRecords(newList); } } sb.Replace("\r\n", "\n"); sb.Replace('\r', '\n'); return(sb.ToString()); }
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 bool ExportBdb() { saveFileDialog.OverwritePrompt = true; saveFileDialog.ValidateNames = true; saveFileDialog.Filter = LanguageManager.TryGetString("misc.filter.bdb") ?? "CGSS Beatmap Bundle (*.bdb)|*.bdb"; saveFileDialog.FileName = $"musicscores_m{_liveID:000}.bdb"; var r = saveFileDialog.ShowDialog(this); if (r == DialogResult.Cancel) { return(false); } var bdbFileName = saveFileDialog.FileName; var difficulties = new Difficulty[] { GetSelectedDifficulty(cboDiffculty1), GetSelectedDifficulty(cboDiffculty2), GetSelectedDifficulty(cboDiffculty3), GetSelectedDifficulty(cboDiffculty4), GetSelectedDifficulty(cboDiffculty5) }; var scores = difficulties.Select(d => _project.Project.GetScore(d)).ToArray(); var isEndingCustom = radEndTimeCustom.Checked; var compiledScores = new CompiledScore[scores.Length]; for (var i = 0; i < scores.Length; ++i) { var score = scores[i]; CompiledScore compiledScore; if (isEndingCustom) { var durationSeconds = double.Parse(txtCustomEndTime.Text); var duration = TimeSpan.FromSeconds(durationSeconds); compiledScore = score.Compile(duration); } else { compiledScore = score.Compile(); } compiledScores[i] = compiledScore; } var connectionString = $"Data Source={bdbFileName}"; if (File.Exists(bdbFileName)) { File.Delete(bdbFileName); } else { SQLiteConnection.CreateFile(bdbFileName); } var liveID = _liveID; using (var connection = new SQLiteConnection(connectionString)) { connection.Open(); using (var transaction = connection.BeginTransaction()) { SQLiteCommand command; using (command = transaction.Connection.CreateCommand()) { command.CommandText = "CREATE TABLE blobs (name TEXT PRIMARY KEY, data BLOB NOT NULL);"; command.ExecuteNonQuery(); } using (command = transaction.Connection.CreateCommand()) { command.CommandText = "INSERT INTO blobs (name, data) VALUES (@name, @data);"; var nameParam = command.Parameters.Add("name", DbType.AnsiString); var dataParam = command.Parameters.Add("data", DbType.Binary); // update: Create Master+ entry, regardless of its existence in original BDB. for (var i = (int)Difficulty.Debut; i <= (int)Difficulty.MasterPlus; ++i) { var compiledScore = compiledScores[i - 1]; var csv = compiledScore.GetCsvString(); var csvData = Encoding.ASCII.GetBytes(csv); nameParam.Value = string.Format(ScoreRecordFormat, liveID, i); dataParam.Value = csvData; command.ExecuteNonQuery(); } nameParam.Value = string.Format(Score2DCharaFormat, liveID); dataParam.Value = Encoding.ASCII.GetBytes(Score2DCharaText); command.ExecuteNonQuery(); nameParam.Value = string.Format(ScoreCyalumeFormat, liveID); dataParam.Value = Encoding.ASCII.GetBytes(ScoreCyalumeText); command.ExecuteNonQuery(); nameParam.Value = string.Format(ScoreLyricsFormat, liveID); dataParam.Value = Encoding.ASCII.GetBytes(ScoreLyricsText); command.ExecuteNonQuery(); } transaction.Commit(); } connection.Close(); } var reportMessageTemplate = LanguageManager.TryGetString("messages.fbuildbeatmap.bdb_scores_exported") ?? "The scores are exported to '{0}'."; var reportMessage = string.Format(reportMessageTemplate, saveFileDialog.FileName); MessageBox.Show(this, reportMessage, AssemblyHelper.GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Information); return(true); Difficulty GetSelectedDifficulty(ComboBox comboBox) { return((Difficulty)(comboBox.SelectedIndex + 1)); } }
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); }