From a092ba1c52dd5f08b1e3ec9658c8a86753b1bcff Mon Sep 17 00:00:00 2001 From: Jared Johnson Date: Sun, 23 Feb 2025 12:16:07 -0500 Subject: [PATCH 1/4] add optional span argument for adding cursors --- src/elements/score.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/elements/score.ts b/src/elements/score.ts index 7cc67463f..82ee6fd88 100644 --- a/src/elements/score.ts +++ b/src/elements/score.ts @@ -64,10 +64,14 @@ export class Score { return this.root.getScrollContainer(); } - addCursor(opts?: { partIndex?: number }): playback.Cursor { + addCursor(opts?: { partIndex?: number; span?: { fromPartIndex: number; toPartIndex: number } }): playback.Cursor { const partIndex = opts?.partIndex ?? 0; + const span = opts?.span ?? { fromPartIndex: partIndex, toPartIndex: partIndex }; + 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); this.cursors.push(cursor); return cursor; From af84d4cd7fcdddde0a892fc5a2cc58c57a5258fe Mon Sep 17 00:00:00 2001 From: Jared Johnson Date: Sun, 23 Feb 2025 12:21:11 -0500 Subject: [PATCH 2/4] use CursorVerticalSpan specification to calculate cursor yRange --- src/elements/score.ts | 7 +++---- src/playback/cursor.ts | 16 ++++++++++++++-- src/playback/types.ts | 2 -- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/elements/score.ts b/src/elements/score.ts index 82ee6fd88..c6a76d261 100644 --- a/src/elements/score.ts +++ b/src/elements/score.ts @@ -64,15 +64,14 @@ export class Score { return this.root.getScrollContainer(); } - addCursor(opts?: { partIndex?: number; span?: { fromPartIndex: number; toPartIndex: number } }): playback.Cursor { + addCursor(opts?: { partIndex?: number; span?: playback.CursorVerticalSpan }): playback.Cursor { const partIndex = opts?.partIndex ?? 0; - const span = opts?.span ?? { fromPartIndex: partIndex, toPartIndex: partIndex }; - util.assert(span.fromPartIndex <= span.toPartIndex, 'fromPartIndex must be less than or equal to toPartIndex'); + const span = opts?.span ?? { fromPartIndex: 0, toPartIndex: this.getPartCount() - 1 }; 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, partIndex, sequence, span); this.cursors.push(cursor); return cursor; } diff --git a/src/playback/cursor.ts b/src/playback/cursor.ts index 02c485d70..c8634c5dc 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,20 +47,25 @@ 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 { + util.assert(span.fromPartIndex <= span.toPartIndex, 'fromPartIndex must be less than or equal to toPartIndex'); + // NumberRange objects indexed by system index for the part. const systemPartYRanges = new Array(); @@ -64,7 +75,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 +128,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[]; From 7e5dc00de6ca7cd7166a10fe4f43c330ea9698e4 Mon Sep 17 00:00:00 2001 From: Jared Johnson Date: Sun, 23 Feb 2025 12:22:10 -0500 Subject: [PATCH 3/4] remove unused partIndex param (which is used to get the correct sequence) --- src/elements/score.ts | 2 +- src/playback/cursor.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/elements/score.ts b/src/elements/score.ts index c6a76d261..47f680714 100644 --- a/src/elements/score.ts +++ b/src/elements/score.ts @@ -71,7 +71,7 @@ export class Score { const sequence = this.getSequences().find((sequence) => sequence.getPartIndex() === partIndex); util.assertDefined(sequence); - const cursor = playback.Cursor.create(this.root.getScrollContainer(), this, partIndex, sequence, span); + 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 c8634c5dc..f2dde78cd 100644 --- a/src/playback/cursor.ts +++ b/src/playback/cursor.ts @@ -60,7 +60,6 @@ export class Cursor { static create( scrollContainer: HTMLElement, score: elements.Score, - partIndex: number, sequence: playback.Sequence, span: CursorVerticalSpan ): Cursor { From bfa737ac8f39091edad8941ad2c04f7fba2cd654 Mon Sep 17 00:00:00 2001 From: Jared Johnson Date: Sun, 23 Feb 2025 12:30:28 -0500 Subject: [PATCH 4/4] move addCursor param assertions and ensure partIndex is always within bounds --- src/elements/score.ts | 9 ++++++++- src/playback/cursor.ts | 2 -- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/elements/score.ts b/src/elements/score.ts index 47f680714..682385de8 100644 --- a/src/elements/score.ts +++ b/src/elements/score.ts @@ -65,8 +65,15 @@ export class Score { } addCursor(opts?: { partIndex?: number; span?: playback.CursorVerticalSpan }): playback.Cursor { + const partCount = this.getPartCount(); + const partIndex = opts?.partIndex ?? 0; - const span = opts?.span ?? { fromPartIndex: 0, toPartIndex: this.getPartCount() - 1 }; + 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); diff --git a/src/playback/cursor.ts b/src/playback/cursor.ts index f2dde78cd..abadbd0cb 100644 --- a/src/playback/cursor.ts +++ b/src/playback/cursor.ts @@ -63,8 +63,6 @@ export class Cursor { sequence: playback.Sequence, span: CursorVerticalSpan ): Cursor { - util.assert(span.fromPartIndex <= span.toPartIndex, 'fromPartIndex must be less than or equal to toPartIndex'); - // NumberRange objects indexed by system index for the part. const systemPartYRanges = new Array();