فهرست منبع

feat: implemented setting stem direction automatically from voice type (main or linked voice)

Matthias Uiberacker 7 سال پیش
والد
کامیت
e7f9e10a09

+ 0 - 11
src/MusicalScore/Graphical/GraphicalStaffEntry.ts

@@ -6,7 +6,6 @@ import {Note} from "../VoiceData/Note";
 import {Slur} from "../VoiceData/Expressions/ContinuousExpressions/Slur";
 import {Voice} from "../VoiceData/Voice";
 import {VoiceEntry} from "../VoiceData/VoiceEntry";
-import {LinkedVoice} from "../VoiceData/LinkedVoice";
 import {GraphicalTie} from "./GraphicalTie";
 import {GraphicalObject} from "./GraphicalObject";
 import {StaffMeasure} from "./StaffMeasure";
@@ -236,16 +235,6 @@ export abstract class GraphicalStaffEntry extends GraphicalObject {
         return false;
     }
 
-    public getMainVoice(): Voice {
-        for (let idx: number = 0, len: number = this.sourceStaffEntry.VoiceEntries.length; idx < len; ++idx) {
-            const voiceEntry: VoiceEntry = this.sourceStaffEntry.VoiceEntries[idx];
-            if (!(voiceEntry.ParentVoice instanceof LinkedVoice)) {
-                return voiceEntry.ParentVoice;
-            }
-        }
-        return this.notes[0][0].sourceNote.ParentVoiceEntry.ParentVoice;
-    }
-
     /**
      * Return the [[StaffEntry]]'s Minimum NoteLength.
      * @returns {Fraction}

+ 34 - 2
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -14,7 +14,7 @@ import {GraphicalMusicPage} from "./GraphicalMusicPage";
 import {GraphicalNote} from "./GraphicalNote";
 import {Beam} from "../VoiceData/Beam";
 import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
-import {VoiceEntry} from "../VoiceData/VoiceEntry";
+import {VoiceEntry, StemDirectionType} from "../VoiceData/VoiceEntry";
 import {OrnamentContainer} from "../VoiceData/OrnamentContainer";
 import {ArticulationEnum} from "../VoiceData/VoiceEntry";
 import {Tuplet} from "../VoiceData/Tuplet";
@@ -852,6 +852,7 @@ export abstract class MusicSheetCalculator {
                                openTuplets: Tuplet[], openBeams: Beam[],
                                octaveShiftValue: OctaveEnum, grace: boolean = false, linkedNotes: Note[] = undefined,
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
+        this.calculateStemDirectionFromVoices(voiceEntry);
         const graphicalNotes: GraphicalNote[] = graphicalStaffEntry.findOrCreateGraphicalNotesListFromVoiceEntry(voiceEntry);
         for (let idx: number = 0, len: number = voiceEntry.Notes.length; idx < len; ++idx) {
             const note: Note = voiceEntry.Notes[idx];
@@ -995,8 +996,8 @@ export abstract class MusicSheetCalculator {
 
     protected layoutVoiceEntries(graphicalStaffEntry: GraphicalStaffEntry): void {
         graphicalStaffEntry.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
-        const isGraceStaffEntry: boolean = graphicalStaffEntry.staffEntryParent !== undefined;
         if (!this.leadSheet) {
+            const isGraceStaffEntry: boolean = graphicalStaffEntry.staffEntryParent !== undefined;
             const graphicalStaffEntryNotes: GraphicalNote[][] = graphicalStaffEntry.notes;
             for (let idx4: number = 0, len4: number = graphicalStaffEntryNotes.length; idx4 < len4; ++idx4) {
                 const graphicalNotes: GraphicalNote[] = graphicalStaffEntryNotes[idx4];
@@ -2108,4 +2109,35 @@ export abstract class MusicSheetCalculator {
             }
         }
     }
+
+    /**
+     * Calculates the desired stem direction depending on the number (or type) of voices.
+     * If more than one voice is there, the main voice (typically the first or upper voice) will get stem up direction.
+     * The others get stem down direction.
+     * @param voiceEntry the voiceEntry for which the stem direction has to be calculated
+     */
+    private calculateStemDirectionFromVoices(voiceEntry: VoiceEntry): void {
+        // Stem direction calculation:
+        const hasLink: boolean = voiceEntry.ParentSourceStaffEntry.Link !== undefined;
+        if (hasLink) {
+            // in case of StaffEntryLink don't check mainVoice / linkedVoice
+            if (voiceEntry === voiceEntry.ParentSourceStaffEntry.VoiceEntries[0]) {
+            // set stem up:
+            voiceEntry.StemDirection = StemDirectionType.Up;
+            return;
+            } else {
+            // set stem down:
+            voiceEntry.StemDirection = StemDirectionType.Down;
+            return;
+            }
+        } else {
+            if (voiceEntry.ParentVoice instanceof LinkedVoice) {
+                // Linked voice: set stem down:
+                voiceEntry.StemDirection = StemDirectionType.Down;
+            } else {
+                // if this voiceEntry belongs to the mainVoice: stem Up
+                voiceEntry.StemDirection = StemDirectionType.Up;
+            }
+        }
+    }
 }

+ 4 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -16,7 +16,7 @@ import {FontStyles} from "../../../Common/Enums/FontStyles";
 import {Fonts} from "../../../Common/Enums/Fonts";
 import {OutlineAndFillStyleEnum, OUTLINE_AND_FILL_STYLE_DICT} from "../DrawingEnums";
 import {Logging} from "../../../Common/Logging";
-import { ArticulationEnum, StemDirection } from "../../VoiceData/VoiceEntry";
+import { ArticulationEnum, StemDirectionType } from "../../VoiceData/VoiceEntry";
 
 /**
  * Helper class, which contains static methods which actually convert
@@ -177,12 +177,12 @@ export class VexFlowConverter {
             duration: duration,
             keys: keys,
         });
-        const wantedStemDirection: StemDirection = notes[0].sourceNote.ParentVoiceEntry.stemDirection;
+        const wantedStemDirection: StemDirectionType = notes[0].sourceNote.ParentVoiceEntry.StemDirection;
         switch (wantedStemDirection) {
-            case(StemDirection.Up):
+            case(StemDirectionType.Up):
                 vfnote.setStemDirection(Vex.Flow.Stem.UP);
                 break;
-            case (StemDirection.Down):
+            case (StemDirectionType.Down):
                 vfnote.setStemDirection(Vex.Flow.Stem.DOWN);
                 break;
             default:

+ 3 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -19,6 +19,7 @@ import {unitInPixels} from "./VexFlowMusicSheetDrawer";
 import {Tuplet} from "../../VoiceData/Tuplet";
 import { RepetitionInstructionEnum } from "../../VoiceData/Instructions/RepetitionInstruction";
 import { SystemLinePosition } from "../SystemLinePosition";
+import { StemDirectionType } from "../../VoiceData/VoiceEntry";
 
 export class VexFlowMeasure extends StaffMeasure {
     constructor(staff: Staff, staffLine: StaffLine = undefined, sourceMeasure: SourceMeasure = undefined) {
@@ -390,7 +391,8 @@ export class VexFlowMeasure extends StaffMeasure {
                 for (const beam of this.beams[voiceID]) {
                     const notes: Vex.Flow.StaveNote[] = [];
                     const staffEntries: VexFlowStaffEntry[] = beam[1];
-                    const autoStemBeam: boolean = staffEntries[0].graphicalNotes[voiceID][0].sourceNote.ParentVoiceEntry.stemDirection === undefined;
+                    const autoStemBeam: boolean = staffEntries[0].graphicalNotes[voiceID][0].sourceNote.
+                                                    ParentVoiceEntry.StemDirection === StemDirectionType.Undefined;
                     for (const entry of staffEntries) {
                         const note: Vex.Flow.StaveNote = (<VexFlowStaffEntry>entry).vfNotes[voiceID];
                         if (note !== undefined) {

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

@@ -2,7 +2,7 @@ import {MusicSheetCalculator} from "../MusicSheetCalculator";
 import {VexFlowGraphicalSymbolFactory} from "./VexFlowGraphicalSymbolFactory";
 import {StaffMeasure} from "../StaffMeasure";
 import {StaffLine} from "../StaffLine";
-import {VoiceEntry, StemDirection} from "../../VoiceData/VoiceEntry";
+import {VoiceEntry} from "../../VoiceData/VoiceEntry";
 import {MusicSystem} from "../MusicSystem";
 import {GraphicalNote} from "../GraphicalNote";
 import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
@@ -27,8 +27,6 @@ import Vex = require("vexflow");
 import {Logging} from "../../../Common/Logging";
 import {unitInPixels} from "./VexFlowMusicSheetDrawer";
 import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
-import {Voice} from "../../VoiceData/Voice";
-import {LinkedVoice} from "../../VoiceData/LinkedVoice";
 import {TechnicalInstruction} from "../../VoiceData/Instructions/TechnicalInstruction";
 import { GraphicalLyricEntry } from "../GraphicalLyricEntry";
 import { GraphicalLabel } from "../GraphicalLabel";
@@ -157,46 +155,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
    */
   protected layoutVoiceEntry(voiceEntry: VoiceEntry, graphicalNotes: GraphicalNote[], graphicalStaffEntry: GraphicalStaffEntry,
                              hasPitchedNote: boolean, isGraceStaffEntry: boolean): void {
-    // Stem direction calculation:
-    if (graphicalNotes.length > 0) {
-      const firstNote: GraphicalNote = graphicalNotes[0];
-      if (firstNote.sourceNote.ParentVoiceEntry !== undefined) {
-        const hasLink: boolean = graphicalStaffEntry.sourceStaffEntry.Link !== undefined;
-        if (hasLink) {
-          // in case of StaffEntryLink don't check mainVoice / linkedVoice
-          if (firstNote.sourceNote.ParentVoiceEntry === graphicalStaffEntry.sourceStaffEntry.VoiceEntries[0]) {
-            // set stem up:
-            voiceEntry.stemDirection = StemDirection.Up;
-            return;
-          } else {
-            // set stem down:
-            voiceEntry.stemDirection = StemDirection.Down;
-            return;
-          }
-        } else {
-          const isMainVoice: boolean = !(firstNote.sourceNote.ParentVoiceEntry.ParentVoice instanceof LinkedVoice);
-          // if mainVoice, direction Up, else direction Down
-          if (isMainVoice) {
-            const mainVoice: Voice = graphicalStaffEntry.getMainVoice();
-
-            if (firstNote.sourceNote.ParentVoiceEntry.ParentVoice === mainVoice) {
-              // set stem up:
-              voiceEntry.stemDirection = StemDirection.Up;
-              return;
-            } else {
-              // two Voices present in same Measure
-              // set stem down:
-              voiceEntry.stemDirection = StemDirection.Down;
-              return;
-            }
-          } else {
-            // set stem down:
-            voiceEntry.stemDirection = StemDirection.Down;
-            return;
-          }
-        }
-      }
-    }
+    return;
   }
 
   /**

+ 10 - 2
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -29,7 +29,6 @@ export class VoiceEntry {
 
     public graceVoiceEntriesBefore: VoiceEntry[];
     public graceVoiceEntriesAfter: VoiceEntry[];
-    public stemDirection: StemDirection = undefined;
 
     private parentVoice: Voice;
     private parentSourceStaffEntry: SourceStaffEntry;
@@ -40,6 +39,7 @@ export class VoiceEntry {
     private lyricsEntries: Dictionary<number, LyricsEntry> = new Dictionary<number, LyricsEntry>();
     private arpeggiosNotesIndices: number[] = [];
     private ornamentContainer: OrnamentContainer;
+    private stemDirection: StemDirectionType = StemDirectionType.Undefined;
 
     public get ParentSourceStaffEntry(): SourceStaffEntry {
         return this.parentSourceStaffEntry;
@@ -78,6 +78,13 @@ export class VoiceEntry {
         this.ornamentContainer = value;
     }
 
+    public get StemDirection(): StemDirectionType {
+        return this.stemDirection;
+    }
+    public set StemDirection(value: StemDirectionType) {
+        this.stemDirection = value;
+    }
+
     public static isSupportedArticulation(articulation: ArticulationEnum): boolean {
         switch (articulation) {
             case ArticulationEnum.accent:
@@ -327,7 +334,8 @@ export enum ArticulationEnum {
     otherarticulation
 }
 
-export enum StemDirection {
+export enum StemDirectionType {
+    Undefined = -1,
     Up = 0,
     Down = 1,
     None = 2