private static string EnsureFlickValid(Note targetNote, Note lastNote) { // Check: rows must not be the same. if (targetNote.Basic.Bar == lastNote.Basic.Bar && targetNote.Basic.IndexInGrid == lastNote.Basic.IndexInGrid) { return("The rows of the notes must be different."); } // Check: columns must not be the same. if (targetNote.Basic.FinishPosition == lastNote.Basic.FinishPosition) { return("The columns of the notes must be different."); } var(firstNote, secondNote) = NoteHelper.Split(targetNote, lastNote); // Check: the first note must not be a hold start. if (firstNote.Helper.IsHoldStart) { return("The first note must not be a hold start note."); } // Check: the second note must not be a hold start. if (secondNote.Helper.IsHoldStart) { return("The second note must not be a hold start note."); } // Check: the first note must not be a note in the middle of a flick group or start of a flick group. if (firstNote.Helper.IsFlickMidway || firstNote.Helper.IsFlickStart) { return("The first note must not be the start or middle of a flick group."); } // Check: the second note must not be a note in the middle of a flick group or end of a flick group. if (secondNote.Helper.IsFlickMidway || secondNote.Helper.IsFlickEnd) { return("The second note must not be the middle or end a flick group."); } // Check: the first note must not be a note in the middle of a slide group or start of a slide group. if (firstNote.Helper.IsSlideMidway || firstNote.Helper.IsSlideStart) { return("The first note must not be the start or middle a slide group."); } // Check: the second note must not be a note in the middle of a slide group or end of a slide group. if (secondNote.Helper.IsSlideMidway || secondNote.Helper.IsSlideEnd) { return("The second note must not be the middle or end a slide group."); } return(null); }
private void EditNoteModeHoldFlick(ScoreEditorHitTestResult hit, MouseEventArgs e) { var editor = _visualizer.Editor; Note lastNote = null; if (editor.HasOneSelectedNote) { lastNote = editor.GetSelectedNote(); } else if (hit.HitAnyNote && editor.HasSelectedNotes) { Debug.Print("You can only select one note to create a hold pair."); return; } Note thisNote = null; var isNoteAdded = false; if (hit.HitAnyNote) { // The clicked note is always selected. thisNote = hit.Note == _lastMouseDownNote ? hit.Note : null; } else if (hit.HitBarGridIntersection) { // If not selected, add a note and select it. thisNote = EditorAddNote(hit); isNoteAdded = true; } // If the user clicked on nothing, then clear all selections. if (thisNote == null) { ClearNoteAndBarSelection(); editor.Invalidate(); return; } // If the user clicked on the same note, just perform the standard note selection. if (lastNote == null || lastNote == thisNote) { thisNote.EditorToggleSelected(); editor.Invalidate(); return; } var relationCreated = false; if (thisNote.Basic.FinishPosition == lastNote.Basic.FinishPosition) { do { // If the selected note is already a hold note (start/end) and there is a hold relation between the // two notes, then switch selection. if (NoteHelper.AreNotesInHoldChain(thisNote, lastNote)) { // Yep just switch selection. Do nothing in this branch. } else { var errStr = EnsureHoldValid(thisNote, lastNote); if (errStr != null) { if (isNoteAdded) { thisNote.Basic.Bar.RemoveNote(thisNote); } Debug.Print(errStr); break; } // Make hold. var(first, second) = NoteHelper.Split(thisNote, lastNote); NoteHelper.MakeHold(first, second); _visualizer.InformProjectModified(); relationCreated = true; } } while (false); } else { do { // If the selected note is already a flick note and there is a flick relation between the // two notes, then switch selection. if (NoteHelper.AreNotesInFlickChain(thisNote, lastNote)) { // Yep just switch selection. Do nothing in this branch. } else { var errStr = EnsureFlickValid(thisNote, lastNote); if (errStr != null) { if (isNoteAdded) { thisNote.Basic.Bar.RemoveNote(thisNote); } Debug.Print(errStr); break; } // Make flick. var(first, second) = NoteHelper.Split(thisNote, lastNote); NoteHelper.MakeFlick(first, second); _visualizer.InformProjectModified(); relationCreated = true; } } while (false); } // Now handle a special case: link flick after a slide. if (!relationCreated) { var(first, second) = NoteHelper.Split(thisNote, lastNote); if (first.Basic.FinishPosition != second.Basic.FinishPosition) { if (first.Helper.IsSlideEnd && second.Helper.IsFlickStart) { NoteHelper.MakeSlideToFlick(first, second); _visualizer.InformProjectModified(); relationCreated = true; } } } if (relationCreated) { thisNote.EditorUnselect(); lastNote.EditorUnselect(); } else { lastNote.EditorUnselect(); thisNote.EditorSelect(); } // Did we created a hold pair? // If so, ensure the pair's start position being the same. if (relationCreated) { if (thisNote.Helper.IsHoldStart) { thisNote.Editor.HoldPair.Basic.StartPosition = thisNote.Basic.StartPosition; } else if (thisNote.Helper.IsHoldEnd) { thisNote.Basic.StartPosition = thisNote.Editor.HoldPair.Basic.StartPosition; } } editor.Invalidate(); }
private static string EnsureHoldValid(Note targetNote, Note lastNote) { // Check: columns must be the same. if (lastNote.Basic.FinishPosition != targetNote.Basic.FinishPosition) { return("Both notes should be on the same column."); } var(firstNote, secondNote) = NoteHelper.Split(targetNote, lastNote); // Check: the first note must be a tap note. if (!firstNote.Helper.IsTap) { return("The first note must be a tap note."); } // Check: the first note must not be a hold note. if (firstNote.Helper.IsHold) { return("The first note must not be a hold start note or hold end note."); } // Check: the second note must not be a hold note. if (secondNote.Helper.IsHold) { return("The second note must not be a hold start note or hold end note."); } var targetBar = targetNote.Basic.Bar; var lastBar = lastNote.Basic.Bar; var firstBarIndex = Math.Min(lastBar.Basic.Index, targetBar.Basic.Index); var secondBarIndex = firstBarIndex == targetBar.Basic.Index ? lastBar.Basic.Index : targetBar.Basic.Index; // Check: no other notes can be between these two notes. var anyNoteInBetween = false; if (secondBarIndex == firstBarIndex) { var firstRow = Math.Min(lastNote.Basic.IndexInGrid, targetNote.Basic.IndexInGrid); var secondRow = firstRow == lastNote.Basic.IndexInGrid ? targetNote.Basic.IndexInGrid : lastNote.Basic.IndexInGrid; anyNoteInBetween = targetBar.Notes.Any(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && firstRow < n.Basic.IndexInGrid && n.Basic.IndexInGrid < secondRow); } else { var score = targetBar.Basic.Score; var firstBar = targetBar.Basic.Index == firstBarIndex ? targetBar : lastBar; var secondBar = firstBar == targetBar ? lastBar : targetBar; var firstRow = firstBar == targetBar ? targetNote.Basic.IndexInGrid : lastNote.Basic.IndexInGrid; var secondRow = firstBar == targetBar ? lastNote.Basic.IndexInGrid : targetNote.Basic.IndexInGrid; foreach (var bar in score.Bars) { if (bar.Basic.Index < firstBarIndex) { continue; } if (bar.Basic.Index > secondBarIndex) { break; } IEnumerable <Note> notes; if (bar == firstBar) { notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && n.Basic.IndexInGrid > firstRow); } else if (bar == secondBar) { notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && n.Basic.IndexInGrid < secondRow); } else { notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition); } anyNoteInBetween = notes.Any(); if (anyNoteInBetween) { break; } } } if (anyNoteInBetween) { return("There must not be any other notes between a hold note pair."); } return(null); }