Пример #1
0
        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;
                }
            }
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
 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;
 }
Пример #4
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);
        }
Пример #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);
        }