예제 #1
0
        public static CompiledScore Compile(this Score score)
        {
            var compiledScore = new CompiledScore();

            CompileTo(score, compiledScore);
            return(compiledScore);
        }
예제 #2
0
        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());
        }
예제 #3
0
        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);
        }
예제 #4
0
        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));
            }
        }
예제 #5
0
        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);
        }