Browse Source

refactor interaction listeners for more flexibility, add rules.UseDefaultVoiceInteractionListener (#55)

sschmidTU 3 years ago
parent
commit
e382b299a1

+ 19 - 40
src/Display/SheetRenderingManager.ts

@@ -1,6 +1,6 @@
 import { IZoomView } from "../Common/Interfaces/IZoomView";
 import { IZoomView } from "../Common/Interfaces/IZoomView";
 import {    MusicSheetDrawer, GraphicalMusicSheet, BoundingBox, DrawingParameters,
 import {    MusicSheetDrawer, GraphicalMusicSheet, BoundingBox, DrawingParameters,
-            MusicSystem, GraphicalVoiceEntry } from "../MusicalScore/Graphical";
+            MusicSystem, EngravingRules} from "../MusicalScore/Graphical";
 import { ScreenViewingRegion } from "./ScreenViewingRegion";
 import { ScreenViewingRegion } from "./ScreenViewingRegion";
 import { PointF2D, Fraction, SizeF2D } from "../Common/DataObjects";
 import { PointF2D, Fraction, SizeF2D } from "../Common/DataObjects";
 import { AbstractZoomView } from "./AbstractZoomView";
 import { AbstractZoomView } from "./AbstractZoomView";
@@ -8,6 +8,7 @@ import { InteractionType } from "../Common/Enums/InteractionType";
 import { AbstractDisplayInteractionManager } from "./AbstractDisplayInteractionManager";
 import { AbstractDisplayInteractionManager } from "./AbstractDisplayInteractionManager";
 import { IUserDisplayInteractionListener } from "../Common/Interfaces/IUserDisplayInteractionListener";
 import { IUserDisplayInteractionListener } from "../Common/Interfaces/IUserDisplayInteractionListener";
 import { PlaybackManager } from "../Playback";
 import { PlaybackManager } from "../Playback";
+import { VoiceEntryInteractionListener } from "./VoiceEntryInteractionListener";
 
 
 export class SheetRenderingManager extends AbstractZoomView implements IZoomView {
 export class SheetRenderingManager extends AbstractZoomView implements IZoomView {
     protected musicSheetDrawer: MusicSheetDrawer;
     protected musicSheetDrawer: MusicSheetDrawer;
@@ -23,13 +24,20 @@ export class SheetRenderingManager extends AbstractZoomView implements IZoomView
     protected internalPreviewImageScale: number = 3.0;
     protected internalPreviewImageScale: number = 3.0;
     protected listeners: IUserDisplayInteractionListener[] = [];
     protected listeners: IUserDisplayInteractionListener[] = [];
     public PlaybackManager: PlaybackManager;
     public PlaybackManager: PlaybackManager;
+    private rules: EngravingRules;
 
 
-    constructor(displayInteractionManager: AbstractDisplayInteractionManager, playbackManager?: PlaybackManager) {
+    constructor(displayInteractionManager: AbstractDisplayInteractionManager, rules: EngravingRules) {
         super(displayInteractionManager);
         super(displayInteractionManager);
+        this.rules = rules;
         this.addZoomView(this);
         this.addZoomView(this);
         this.lockRanges = true;
         this.lockRanges = true;
         this.TopBarHeightInPixel = 70;
         this.TopBarHeightInPixel = 70;
         this.BottomBarHeightInPixel = 0;
         this.BottomBarHeightInPixel = 0;
+
+        if (this.rules.UseDefaultVoiceInteractionListener) { // default: true
+            // OSMD default listener (play voice entry, set playback position at voice entry). Can be removed.
+            this.listeners.push(new VoiceEntryInteractionListener(this));
+        }
     }
     }
 
 
     public addListener(listener: IUserDisplayInteractionListener): void {
     public addListener(listener: IUserDisplayInteractionListener): void {
@@ -50,34 +58,22 @@ export class SheetRenderingManager extends AbstractZoomView implements IZoomView
         if (!this.SingleTouchDisabled) {
         if (!this.SingleTouchDisabled) {
             const relPos: PointF2D = new PointF2D(relPosX, relPosY);
             const relPos: PointF2D = new PointF2D(relPosX, relPosY);
             this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.SingleTouch);
             this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.SingleTouch);
-            for (const listener of this.listeners) {
-                listener.userDisplayInteraction(relPos, PosInUnits, InteractionType.SingleTouch);
-            }
         }
         }
     }
     }
     protected unitPosDoubleTouched(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
     protected unitPosDoubleTouched(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
         if (!this.DoubleTouchDisabled) {
         if (!this.DoubleTouchDisabled) {
             const relPos: PointF2D = new PointF2D(relPosX, relPosY);
             const relPos: PointF2D = new PointF2D(relPosX, relPosY);
             this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.DoubleTouch);
             this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.DoubleTouch);
-            for (const listener of this.listeners) {
-                listener.userDisplayInteraction(relPos, PosInUnits, InteractionType.DoubleTouch);
-            }
         }
         }
     }
     }
     protected unitPosTouchDown(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
     protected unitPosTouchDown(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.TouchDown);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.TouchDown);
-        for (const listener of this.listeners) {
-            listener.userDisplayInteraction(new PointF2D(relPosX, relPosY), PosInUnits, InteractionType.TouchDown);
-        }
         this.yOffsetMouseDown = PosInUnits.y;
         this.yOffsetMouseDown = PosInUnits.y;
     }
     }
     protected unitPosTouchUp(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
     protected unitPosTouchUp(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.TouchUp);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.TouchUp);
-        for (const listener of this.listeners) {
-            listener.userDisplayInteraction(new PointF2D(relPosX, relPosY), PosInUnits, InteractionType.TouchUp);
-        }
         if (this.displayInteractionManager.WasZoomGestureActive === false) {
         if (this.displayInteractionManager.WasZoomGestureActive === false) {
             this.unlockFromCursorIfNecessary(PosInUnits);
             this.unlockFromCursorIfNecessary(PosInUnits);
         }
         }
@@ -86,9 +82,6 @@ export class SheetRenderingManager extends AbstractZoomView implements IZoomView
     protected unitPosMove(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
     protected unitPosMove(PosInUnits: PointF2D, relPosX: number, relPosY: number): void {
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         const relPos: PointF2D = new PointF2D(relPosX, relPosY);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.Move);
         this.handleUserDisplayInteraction(relPos, PosInUnits, InteractionType.Move);
-        for (const listener of this.listeners) {
-            listener.userDisplayInteraction(new PointF2D(relPosX, relPosY), PosInUnits, InteractionType.Move);
-        }
         this.unlockFromCursorIfNecessary(PosInUnits);
         this.unlockFromCursorIfNecessary(PosInUnits);
     }
     }
 
 
@@ -240,31 +233,14 @@ export class SheetRenderingManager extends AbstractZoomView implements IZoomView
         switch (type) {
         switch (type) {
             case InteractionType.TouchDown:
             case InteractionType.TouchDown:
             case InteractionType.SingleTouch:
             case InteractionType.SingleTouch:
-            case InteractionType.DoubleTouch: {
-                const clickVe: GraphicalVoiceEntry = this.graphicalMusicSheet.GetNearestVoiceEntry(positionOnMusicSheet);
-                // set cursor and/or start/end marker position
-
-                if (clickVe) {
-                    if (clickVe.parentStaffEntry.parentVerticalContainer !== undefined) {
-                        const clickedTimeStamp: Fraction = clickVe.parentStaffEntry.parentVerticalContainer.AbsoluteTimestamp;
-                        this.setStartPosition(clickedTimeStamp);
-                        // playback clicked note
-                        if (clickVe.notes[0]?.sourceNote.Pitch !== undefined) {
-                            this.PlaybackManager?.playVoiceEntry(clickVe.parentVoiceEntry);
-                        }
-                    }
+            case InteractionType.DoubleTouch:
+            case InteractionType.TouchUp:
+            case InteractionType.TouchDown:
+            case InteractionType.Move:
+                for (const listener of this.listeners) {
+                    listener.userDisplayInteraction(relativePositionOnDisplay, positionOnMusicSheet, type);
                 }
                 }
                 break;
                 break;
-            }
-            case InteractionType.TouchUp: {
-                break;
-            }
-            case InteractionType.TouchDown: {
-                break;
-            }
-            case InteractionType.Move: {
-                break;
-            }
             default:
             default:
                 throw new Error("type");
                 throw new Error("type");
         }
         }
@@ -279,4 +255,7 @@ export class SheetRenderingManager extends AbstractZoomView implements IZoomView
         this.PlaybackManager?.reset();
         this.PlaybackManager?.reset();
     }
     }
 
 
+    public get GraphicalMusicSheet(): GraphicalMusicSheet {
+        return this.graphicalMusicSheet;
+    }
 }
 }

+ 41 - 0
src/Display/VoiceEntryInteractionListener.ts

@@ -0,0 +1,41 @@
+import { IUserDisplayInteractionListener } from "../Common/Interfaces/IUserDisplayInteractionListener";
+import { PointF2D, Fraction } from "../Common/DataObjects";
+import { InteractionType } from "../Common/Enums/InteractionType";
+import { GraphicalVoiceEntry } from "../MusicalScore/Graphical";
+import { SheetRenderingManager } from "./SheetRenderingManager";
+
+export class VoiceEntryInteractionListener implements IUserDisplayInteractionListener {
+    private renderingManager: SheetRenderingManager;
+
+    constructor(renderingManager: SheetRenderingManager) {
+        this.renderingManager = renderingManager;
+    }
+
+    userDisplayInteraction(relativePosition: PointF2D, positionInSheetUnits: PointF2D, type: InteractionType): void {
+        switch (type) {
+            case InteractionType.TouchDown:
+            case InteractionType.SingleTouch:
+            case InteractionType.DoubleTouch: {
+                const clickVe: GraphicalVoiceEntry = this.renderingManager.GraphicalMusicSheet.GetNearestVoiceEntry(
+                    positionInSheetUnits,
+                );
+
+                // set cursor and/or start/end marker position
+                if (clickVe) {
+                    if (clickVe.parentStaffEntry.parentVerticalContainer !== undefined) {
+                        const clickedTimeStamp: Fraction = clickVe.parentStaffEntry.parentVerticalContainer.AbsoluteTimestamp;
+                        this.renderingManager.setStartPosition(clickedTimeStamp);
+                        // playback clicked note
+                        if (clickVe.notes[0]?.sourceNote.Pitch !== undefined) {
+                            this.renderingManager.PlaybackManager?.playVoiceEntry(clickVe.parentVoiceEntry);
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+                // Do nothing
+                break;
+        }
+    }
+}

+ 2 - 0
src/MusicalScore/Graphical/EngravingRules.ts

@@ -344,6 +344,8 @@ export class EngravingRules {
      * If you experience notes being skipped during playback, try increasing this interval slightly (e.g. 0.02 -> 0.03).
      * If you experience notes being skipped during playback, try increasing this interval slightly (e.g. 0.02 -> 0.03).
      */
      */
     public PlaybackSkipNotesSafetyInterval: number = 0.02;
     public PlaybackSkipNotesSafetyInterval: number = 0.02;
+    /** Whether to use OSMD's default voice entry interaction listener that plays voice entry on click etc. */
+    public UseDefaultVoiceInteractionListener: boolean = true;
 
 
     constructor() {
     constructor() {
         this.loadDefaultValues();
         this.loadDefaultValues();

+ 1 - 1
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -67,7 +67,7 @@ export class OpenSheetMusicDisplay {
         this.backendType = BackendType.SVG; // default, can be changed by options
         this.backendType = BackendType.SVG; // default, can be changed by options
         this.setOptions(options);
         this.setOptions(options);
         this.interactionManager = new WebDisplayInteractionManager(this.container);
         this.interactionManager = new WebDisplayInteractionManager(this.container);
-        this.renderingManager = new WebSheetRenderingManager(this.interactionManager);
+        this.renderingManager = new WebSheetRenderingManager(this.interactionManager, this.rules);
     }
     }
 
 
     private cursorsOptions: CursorOptions[] = [];
     private cursorsOptions: CursorOptions[] = [];