Przeglądaj źródła

fix(invisible notes): invisible rests formatting fixed by adding ghost notes

main changes:
VexFlowMeasure: adding Ghost note
MusicSheetCalculator: don't skip voice entries with invisible notes for handleVoiceEntry(), causes problems
adds some handling (skipping) of invisible notes in places like beams, tuplets and voice entry handling.

this commit was done copying the changes from the fix/invisibleRestNotesFormatting branch to develop,
because that branch was created from the fingering feature branch and shows irrelevant changes in the PR.
sschmidTU 6 lat temu
rodzic
commit
3b0e19de00

+ 6 - 13
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -1122,21 +1122,11 @@ export abstract class MusicSheetCalculator {
                                openTuplets: Tuplet[], openBeams: Beam[],
                                openTuplets: Tuplet[], openBeams: Beam[],
                                octaveShiftValue: OctaveEnum, linkedNotes: Note[] = undefined,
                                octaveShiftValue: OctaveEnum, linkedNotes: Note[] = undefined,
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
-        let voiceEntryHasPrintableNotes: boolean = false;
-        for (const note of voiceEntry.Notes) {
-            if (note.PrintObject) {
-                voiceEntryHasPrintableNotes = true;
-                break;
-            }
-        }
-        if (!voiceEntryHasPrintableNotes) {
-            return; // do not create a GraphicalVoiceEntry without graphical notes in it, will cause problems
-        }
         this.calculateStemDirectionFromVoices(voiceEntry);
         this.calculateStemDirectionFromVoices(voiceEntry);
         const gve: GraphicalVoiceEntry = graphicalStaffEntry.findOrCreateGraphicalVoiceEntry(voiceEntry);
         const gve: GraphicalVoiceEntry = graphicalStaffEntry.findOrCreateGraphicalVoiceEntry(voiceEntry);
         for (let idx: number = 0, len: number = voiceEntry.Notes.length; idx < len; ++idx) {
         for (let idx: number = 0, len: number = voiceEntry.Notes.length; idx < len; ++idx) {
             const note: Note = voiceEntry.Notes[idx];
             const note: Note = voiceEntry.Notes[idx];
-            if (note === undefined || !note.PrintObject) {
+            if (note === undefined) {
                 continue;
                 continue;
             }
             }
             if (sourceStaffEntry !== undefined && sourceStaffEntry.Link !== undefined && linkedNotes !== undefined && linkedNotes.indexOf(note) > -1) {
             if (sourceStaffEntry !== undefined && sourceStaffEntry.Link !== undefined && linkedNotes !== undefined && linkedNotes.indexOf(note) > -1) {
@@ -1155,10 +1145,10 @@ export abstract class MusicSheetCalculator {
             graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(gve, graphicalNote);
             graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(gve, graphicalNote);
             graphicalNote.PositionAndShape.calculateBoundingBox();
             graphicalNote.PositionAndShape.calculateBoundingBox();
             if (!this.leadSheet) {
             if (!this.leadSheet) {
-                if (note.NoteBeam !== undefined) {
+                if (note.NoteBeam !== undefined && note.PrintObject) {
                     this.handleBeam(graphicalNote, note.NoteBeam, openBeams);
                     this.handleBeam(graphicalNote, note.NoteBeam, openBeams);
                 }
                 }
-                if (note.NoteTuplet !== undefined) {
+                if (note.NoteTuplet !== undefined && note.PrintObject) {
                     this.handleTuplet(graphicalNote, note.NoteTuplet, openTuplets);
                     this.handleTuplet(graphicalNote, note.NoteTuplet, openTuplets);
                 }
                 }
             }
             }
@@ -1451,6 +1441,9 @@ export abstract class MusicSheetCalculator {
             endGse = this.graphicalMusicSheet.GetGraphicalFromSourceStaffEntry(tie.Notes[i].ParentStaffEntry);
             endGse = this.graphicalMusicSheet.GetGraphicalFromSourceStaffEntry(tie.Notes[i].ParentStaffEntry);
             endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Notes[i]);
             endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Notes[i]);
             if (startNote !== undefined && endNote !== undefined && endGse !== undefined) {
             if (startNote !== undefined && endNote !== undefined && endGse !== undefined) {
+                if (!startNote.sourceNote.PrintObject || !endNote.sourceNote.PrintObject) {
+                    continue;
+                }
                 const graphicalTie: GraphicalTie = this.createGraphicalTie(tie, startGse, endGse, startNote, endNote);
                 const graphicalTie: GraphicalTie = this.createGraphicalTie(tie, startGse, endGse, startNote, endNote);
                 startGse.GraphicalTies.push(graphicalTie);
                 startGse.GraphicalTies.push(graphicalTie);
                 if (this.staffEntriesWithGraphicalTies.indexOf(startGse) >= 0) {
                 if (this.staffEntriesWithGraphicalTies.indexOf(startGse) >= 0) {

+ 0 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -182,7 +182,6 @@ export class VexFlowConverter {
     }
     }
 
 
     public static GhostNote(frac: Fraction): Vex.Flow.GhostNote {
     public static GhostNote(frac: Fraction): Vex.Flow.GhostNote {
-        // const frac: Fraction = notes[0].graphicalNoteLength;
         return new Vex.Flow.GhostNote({
         return new Vex.Flow.GhostNote({
             duration: VexFlowConverter.duration(frac, false),
             duration: VexFlowConverter.duration(frac, false),
         });
         });

+ 7 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -434,7 +434,6 @@ export class VexFlowMeasure extends GraphicalMeasure {
 
 
             // check if this voice has just been found the first time:
             // check if this voice has just been found the first time:
             if (latestVoiceTimestamp === undefined) {
             if (latestVoiceTimestamp === undefined) {
-
                 // if this voice is new, check for a gap from measure start to the start of the current voice entry:
                 // if this voice is new, check for a gap from measure start to the start of the current voice entry:
                 const gapFromMeasureStart: Fraction = Fraction.minus(gNotesStartTimestamp, this.parentSourceMeasure.AbsoluteTimestamp);
                 const gapFromMeasureStart: Fraction = Fraction.minus(gNotesStartTimestamp, this.parentSourceMeasure.AbsoluteTimestamp);
                 if (gapFromMeasureStart.RealValue > 0) {
                 if (gapFromMeasureStart.RealValue > 0) {
@@ -651,6 +650,8 @@ export class VexFlowMeasure extends GraphicalMeasure {
                 if (gve.notes[0].sourceNote.PrintObject) {
                 if (gve.notes[0].sourceNote.PrintObject) {
                     (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.StaveNote(gve);
                     (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.StaveNote(gve);
                 } else {
                 } else {
+                    // don't render note. add ghost note, otherwise Vexflow can have issues with layouting when voices not complete.
+                    (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.GhostNote(gve.notes[0].sourceNote.Length);
                     graceGVoiceEntriesBefore = []; // if note is not rendered, its grace notes might need to be removed
                     graceGVoiceEntriesBefore = []; // if note is not rendered, its grace notes might need to be removed
                     continue;
                     continue;
                 }
                 }
@@ -665,7 +666,6 @@ export class VexFlowMeasure extends GraphicalMeasure {
                         }
                         }
                     }
                     }
                     const graceNoteGroup: Vex.Flow.GraceNoteGroup = new Vex.Flow.GraceNoteGroup(graceNotes, graceSlur);
                     const graceNoteGroup: Vex.Flow.GraceNoteGroup = new Vex.Flow.GraceNoteGroup(graceNotes, graceSlur);
-                    // (gve as VexFlowVoiceEntry).vfStaveNote.addModifier(0, graceNoteGroup.beamNotes()); // beams in handleBeam now
                     (gve as VexFlowVoiceEntry).vfStaveNote.addModifier(0, graceNoteGroup);
                     (gve as VexFlowVoiceEntry).vfStaveNote.addModifier(0, graceNoteGroup);
                     graceGVoiceEntriesBefore = [];
                     graceGVoiceEntriesBefore = [];
                 }
                 }
@@ -707,6 +707,11 @@ export class VexFlowMeasure extends GraphicalMeasure {
                 }
                 }
 
 
                 const vexFlowVoiceEntry: VexFlowVoiceEntry = voiceEntry as VexFlowVoiceEntry;
                 const vexFlowVoiceEntry: VexFlowVoiceEntry = voiceEntry as VexFlowVoiceEntry;
+                if (voiceEntry.notes.length === 0 || !voiceEntry.notes[0] || !voiceEntry.notes[0].sourceNote.PrintObject) {
+                    // GhostNote, don't add modifiers like in-measure clefs
+                    this.vfVoices[voice.VoiceId].addTickable(vexFlowVoiceEntry.vfStaveNote);
+                    continue;
+                }
 
 
                 // check for in-measure clefs:
                 // check for in-measure clefs:
                 // only add clefs in main voice (to not add them twice)
                 // only add clefs in main voice (to not add them twice)

+ 2 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -390,14 +390,14 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
 
 
     let vfStartNote: Vex.Flow.StaveNote = undefined;
     let vfStartNote: Vex.Flow.StaveNote = undefined;
     let startNoteIndexInTie: number = 0;
     let startNoteIndexInTie: number = 0;
-    if (startNote !== undefined) {
+    if (startNote !== undefined && startNote.vfnote !== undefined && startNote.vfnote.length >= 2) {
       vfStartNote = startNote.vfnote[0];
       vfStartNote = startNote.vfnote[0];
       startNoteIndexInTie = startNote.vfnote[1];
       startNoteIndexInTie = startNote.vfnote[1];
     }
     }
 
 
     let vfEndNote: Vex.Flow.StaveNote = undefined;
     let vfEndNote: Vex.Flow.StaveNote = undefined;
     let endNoteIndexInTie: number = 0;
     let endNoteIndexInTie: number = 0;
-    if (endNote !== undefined) {
+    if (endNote !== undefined && endNote.vfnote !== undefined && endNote.vfnote.length >= 2) {
       vfEndNote = endNote.vfnote[0];
       vfEndNote = endNote.vfnote[0];
       endNoteIndexInTie = endNote.vfnote[1];
       endNoteIndexInTie = endNote.vfnote[1];
     }
     }

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -29,7 +29,7 @@ export class VexFlowStaffEntry extends GraphicalStaffEntry {
         for (const gve of this.graphicalVoiceEntries as VexFlowVoiceEntry[]) {
         for (const gve of this.graphicalVoiceEntries as VexFlowVoiceEntry[]) {
             if (gve.vfStaveNote) {
             if (gve.vfStaveNote) {
                 gve.vfStaveNote.setStave(stave);
                 gve.vfStaveNote.setStave(stave);
-                if (!gve.vfStaveNote.preFormatted) {
+                if (!gve.vfStaveNote.preFormatted || gve.vfStaveNote.getBoundingBox() === null) {
                     continue;
                     continue;
                 }
                 }
                 gve.applyBordersFromVexflow();
                 gve.applyBordersFromVexflow();

+ 3 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowVoiceEntry.ts

@@ -12,6 +12,9 @@ export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
 
 
     public applyBordersFromVexflow(): void {
     public applyBordersFromVexflow(): void {
         const staveNote: any = (this.vfStaveNote as any);
         const staveNote: any = (this.vfStaveNote as any);
+        if (!staveNote.getNoteHeadBeginX) {
+            return;
+        }
         const boundingBox: any = staveNote.getBoundingBox();
         const boundingBox: any = staveNote.getBoundingBox();
         const modifierWidth: number = staveNote.getNoteHeadBeginX() - boundingBox.x;
         const modifierWidth: number = staveNote.getNoteHeadBeginX() - boundingBox.x;