Browse Source

fix(Metronome marks): Draw all metronome marks, not just in first measure (#804)

squash-merge #848

* Addex fix for multiple metronome marks. Fixes #804

* fix metronome mark in first pickup measure, add osmd function test metronome marks (#804)

Co-authored-by: sschmid <s.schmid@phonicscore.com>
Benjamin Giesinger 4 years ago
parent
commit
f37cabba98

+ 8 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -613,14 +613,18 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
   }
 
   protected createMetronomeMark(metronomeExpression: InstantaneousTempoExpression): void {
-    const vfStave: Vex.Flow.Stave = (this.graphicalMusicSheet.MeasureList[0][0] as VexFlowMeasure).getVFStave();
+    // note: sometimes MeasureNumber is 0 here, e.g. in Christbaum, maybe because of pickup measure (auftakt)
+    const measureNumber: number = Math.max(metronomeExpression.ParentMultiTempoExpression.SourceMeasureParent.MeasureNumber - 1, 0);
+    const staffNumber: number = Math.max(metronomeExpression.StaffNumber - 1, 0);
+    const firstMetronomeMark: boolean = measureNumber === 0 && staffNumber === 0;
+    const vfStave: Vex.Flow.Stave = (this.graphicalMusicSheet.MeasureList[measureNumber][staffNumber] as VexFlowMeasure).getVFStave();
     //vfStave.addModifier(new Vex.Flow.StaveTempo( // needs Vexflow PR
     let vexflowDuration: string = "q";
     if (metronomeExpression.beatUnit) {
       const duration: Fraction = NoteTypeHandler.getNoteDurationFromType(metronomeExpression.beatUnit);
       vexflowDuration = VexFlowConverter.duration(duration, false);
     }
-    // const noteType: NoteType = NoteTypeHandler.StringToNoteType(metronomeExpression.beatUnit);
+
     vfStave.setTempo(
       {
           bpm: metronomeExpression.TempoInBpm,
@@ -630,9 +634,9 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       this.rules.MetronomeMarkYShift * unitInPixels);
        // -50, -30), 0); //needs Vexflow PR
        //.setShiftX(-50);
-
+    const xShift: number = firstMetronomeMark ? this.rules.MetronomeMarkXShift * unitInPixels : 0;
     (<any>vfStave.getModifiers()[vfStave.getModifiers().length - 1]).setShiftX(
-      this.rules.MetronomeMarkXShift * unitInPixels
+      xShift
     );
     // TODO calculate bounding box of metronome mark instead of hacking skyline to fix lyricist collision
     const skyline: number[] = this.graphicalMusicSheet.MeasureList[0][0].ParentStaffLine.SkyLine;

+ 1 - 1
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -218,7 +218,7 @@ export enum AlignRestOption {
 export enum FillEmptyMeasuresWithWholeRests {
     No = 0,
     YesVisible = 1,
-    YesInvisible = 2
+    YesInvisible = 2 // fill with invisible whole rests
 }
 
 export enum BackendType {

+ 18 - 0
test/data/OSMD_function_test_all.xml

@@ -83,6 +83,15 @@
           <line>2</line>
           </clef>
         </attributes>
+      <direction placement="above">
+        <direction-type>
+          <metronome>
+            <beat-unit>quarter</beat-unit>
+            <per-minute>60</per-minute>
+          </metronome>
+        </direction-type>
+        <sound tempo="40"/>
+      </direction>
       <note default-x="114.16" default-y="-15.00">
         <pitch>
           <step>C</step>
@@ -354,6 +363,15 @@
           <system-distance>97.03</system-distance>
           </system-layout>
         </print>
+      <direction placement="above">
+        <direction-type>
+          <metronome>
+            <beat-unit>half</beat-unit>
+            <per-minute>110</per-minute>
+          </metronome>
+        </direction-type>
+        <sound tempo="40"/>
+      </direction>
       <note default-x="96.95" default-y="-15.00">
         <pitch>
           <step>C</step>

BIN
test/data/OSMD_function_test_metronome_marks.mxl