diff --git a/src/elements/score.ts b/src/elements/score.ts index 7cc67463f..682385de8 100644 --- a/src/elements/score.ts +++ b/src/elements/score.ts @@ -64,11 +64,21 @@ export class Score { return this.root.getScrollContainer(); } - addCursor(opts?: { partIndex?: number }): playback.Cursor { + addCursor(opts?: { partIndex?: number; span?: playback.CursorVerticalSpan }): playback.Cursor { + const partCount = this.getPartCount(); + const partIndex = opts?.partIndex ?? 0; + util.assert(0 <= partIndex && partIndex < partCount, 'partIndex out of bounds'); + + const span = opts?.span ?? { fromPartIndex: 0, toPartIndex: 0 }; + util.assert(0 <= span.fromPartIndex && span.fromPartIndex < partCount, 'fromPartIndex out of bounds'); + util.assert(0 <= span.toPartIndex && span.toPartIndex < partCount, 'toPartIndex out of bounds'); + util.assert(span.fromPartIndex <= span.toPartIndex, 'fromPartIndex must be less than or equal to toPartIndex'); + const sequence = this.getSequences().find((sequence) => sequence.getPartIndex() === partIndex); util.assertDefined(sequence); - const cursor = playback.Cursor.create(this.root.getScrollContainer(), this, partIndex, sequence); + + const cursor = playback.Cursor.create(this.root.getScrollContainer(), this, sequence, span); this.cursors.push(cursor); return cursor; } diff --git a/src/playback/cursor.ts b/src/playback/cursor.ts index 02c485d70..abadbd0cb 100644 --- a/src/playback/cursor.ts +++ b/src/playback/cursor.ts @@ -24,12 +24,18 @@ type EventMap = { change: CursorState; }; +export type CursorVerticalSpan = { + fromPartIndex: number; + toPartIndex: number; +}; + export class Cursor { private scroller: Scroller; private states: CursorState[]; private sequence: playback.Sequence; private cheapLocator: CheapLocator; private expensiveLocator: ExpensiveLocator; + private span: CursorVerticalSpan; private topic = new events.Topic(); private index = 0; @@ -41,19 +47,21 @@ export class Cursor { sequence: playback.Sequence; cheapLocator: CheapLocator; expensiveLocator: ExpensiveLocator; + span: CursorVerticalSpan; }) { this.scroller = opts.scroller; this.states = opts.states; this.sequence = opts.sequence; this.cheapLocator = opts.cheapLocator; this.expensiveLocator = opts.expensiveLocator; + this.span = opts.span; } static create( scrollContainer: HTMLElement, score: elements.Score, - partIndex: number, - sequence: playback.Sequence + sequence: playback.Sequence, + span: CursorVerticalSpan ): Cursor { // NumberRange objects indexed by system index for the part. const systemPartYRanges = new Array(); @@ -64,7 +72,7 @@ export class Cursor { .getMeasures() .flatMap((measure) => measure.getFragments()) .flatMap((fragment) => fragment.getParts()) - .filter((part) => part.getIndex() === partIndex) + .filter((part) => span.fromPartIndex <= part.getIndex() && part.getIndex() <= span.toPartIndex) .map((part) => part.rect()) ); const yRange = new util.NumberRange(rect.top(), rect.bottom()); @@ -117,6 +125,7 @@ export class Cursor { sequence, cheapLocator, expensiveLocator, + span, }); } diff --git a/src/playback/types.ts b/src/playback/types.ts index 6a5e249c2..999a6a140 100644 --- a/src/playback/types.ts +++ b/src/playback/types.ts @@ -2,8 +2,6 @@ import * as elements from '@/elements'; import { NumberRange } from '@/util'; import { DurationRange } from './durationrange'; -export type CursorVerticalSpan = 'system' | 'part'; - export type SequenceEntry = { anchorElement: PlaybackElement; activeElements: PlaybackElement[];