@coderline/alphatab 1.9.0-alpha.1860 → 1.9.0-alpha.1869
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +169 -31
- package/dist/alphaTab.d.ts +57 -2
- package/dist/alphaTab.js +169 -31
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +1 -1
package/dist/alphaTab.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.9.0-alpha.
|
|
2
|
+
* alphaTab v1.9.0-alpha.1869 (develop, build 1869)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2026, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -186,9 +186,9 @@ class AlphaTabError extends Error {
|
|
|
186
186
|
* @internal
|
|
187
187
|
*/
|
|
188
188
|
class VersionInfo {
|
|
189
|
-
static version = "1.9.0-alpha.
|
|
190
|
-
static date = "2026-07-
|
|
191
|
-
static commit = "
|
|
189
|
+
static version = "1.9.0-alpha.1869";
|
|
190
|
+
static date = "2026-07-19T03:42:49.478Z";
|
|
191
|
+
static commit = "2889cac4e359a41b6f24a82034e6f6ba4f9f4c4f";
|
|
192
192
|
static print(print) {
|
|
193
193
|
print(`alphaTab ${VersionInfo.version}`);
|
|
194
194
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -29197,11 +29197,45 @@ class PlayerSettings {
|
|
|
29197
29197
|
* @since 0.9.7
|
|
29198
29198
|
* @defaultValue `true`
|
|
29199
29199
|
* @category Player
|
|
29200
|
+
* @json_read_only
|
|
29200
29201
|
* @remarks
|
|
29201
29202
|
* This setting configures whether alphaTab provides the default user interaction features like selection of the playback range and "seek on click".
|
|
29202
29203
|
* By default users can select the desired playback range with the mouse and also jump to individual beats by click. This behavior can be contolled with this setting.
|
|
29204
|
+
* @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
|
|
29205
|
+
*/
|
|
29206
|
+
get enableUserInteraction() {
|
|
29207
|
+
return this.enableSeekToClick || this.enablePlaybackRangeSelection;
|
|
29208
|
+
}
|
|
29209
|
+
/**
|
|
29210
|
+
* @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
|
|
29211
|
+
*/
|
|
29212
|
+
set enableUserInteraction(value) {
|
|
29213
|
+
this.enableSeekToClick = value;
|
|
29214
|
+
this.enablePlaybackRangeSelection = value;
|
|
29215
|
+
this.resetPlaybackRangeOnClick = value;
|
|
29216
|
+
}
|
|
29217
|
+
/**
|
|
29218
|
+
* Whether the a click on the music sheet triggers a player seek to the note/beat at the
|
|
29219
|
+
* clicked location.
|
|
29220
|
+
* @since 1.9.0
|
|
29221
|
+
* @defaultValue `true`
|
|
29222
|
+
* @category Player
|
|
29223
|
+
*/
|
|
29224
|
+
enableSeekToClick = true;
|
|
29225
|
+
/**
|
|
29226
|
+
* Whether user click and drag results in a selection defining the playback range.
|
|
29227
|
+
* @since 1.9.0
|
|
29228
|
+
* @defaultValue `true`
|
|
29229
|
+
* @category Player
|
|
29203
29230
|
*/
|
|
29204
|
-
|
|
29231
|
+
enablePlaybackRangeSelection = true;
|
|
29232
|
+
/**
|
|
29233
|
+
* Whether a simple click (no range drag) should reset the current playback range.
|
|
29234
|
+
* @since 1.9.0
|
|
29235
|
+
* @defaultValue `true`
|
|
29236
|
+
* @category Player
|
|
29237
|
+
*/
|
|
29238
|
+
resetPlaybackRangeOnClick = true;
|
|
29205
29239
|
/**
|
|
29206
29240
|
* The X-offset to add when scrolling.
|
|
29207
29241
|
* @since 0.9.6
|
|
@@ -30358,7 +30392,9 @@ class PlayerSettingsSerializer {
|
|
|
30358
30392
|
o.set("enablecursor", obj.enableCursor);
|
|
30359
30393
|
o.set("enableanimatedbeatcursor", obj.enableAnimatedBeatCursor);
|
|
30360
30394
|
o.set("enableelementhighlighting", obj.enableElementHighlighting);
|
|
30361
|
-
o.set("
|
|
30395
|
+
o.set("enableseektoclick", obj.enableSeekToClick);
|
|
30396
|
+
o.set("enableplaybackrangeselection", obj.enablePlaybackRangeSelection);
|
|
30397
|
+
o.set("resetplaybackrangeonclick", obj.resetPlaybackRangeOnClick);
|
|
30362
30398
|
o.set("scrolloffsetx", obj.scrollOffsetX);
|
|
30363
30399
|
o.set("scrolloffsety", obj.scrollOffsetY);
|
|
30364
30400
|
o.set("scrollmode", obj.scrollMode);
|
|
@@ -30401,6 +30437,15 @@ class PlayerSettingsSerializer {
|
|
|
30401
30437
|
case "enableuserinteraction":
|
|
30402
30438
|
obj.enableUserInteraction = v;
|
|
30403
30439
|
return true;
|
|
30440
|
+
case "enableseektoclick":
|
|
30441
|
+
obj.enableSeekToClick = v;
|
|
30442
|
+
return true;
|
|
30443
|
+
case "enableplaybackrangeselection":
|
|
30444
|
+
obj.enablePlaybackRangeSelection = v;
|
|
30445
|
+
return true;
|
|
30446
|
+
case "resetplaybackrangeonclick":
|
|
30447
|
+
obj.resetPlaybackRangeOnClick = v;
|
|
30448
|
+
return true;
|
|
30404
30449
|
case "scrolloffsetx":
|
|
30405
30450
|
obj.scrollOffsetX = v;
|
|
30406
30451
|
return true;
|
|
@@ -45399,6 +45444,16 @@ class BeatContainerGlyphBase extends Glyph {
|
|
|
45399
45444
|
scaleToWidth(beatWidth) {
|
|
45400
45445
|
this.width = beatWidth;
|
|
45401
45446
|
}
|
|
45447
|
+
/**
|
|
45448
|
+
* Repositions this beat so its {@link onTimeX} anchor lands at `target`, used for the
|
|
45449
|
+
* centered full-bar note/rest (see {@link BarLayoutingInfo.isCenteredFullBar}). The default
|
|
45450
|
+
* shifts the whole container, matching the regular (non-centered) positioning formula.
|
|
45451
|
+
* {@link BeatContainerGlyph} overrides this to shift only its ink, keeping `x`/`width`
|
|
45452
|
+
* spanning the full bar so bounds lookups and skyline emission stay correct.
|
|
45453
|
+
*/
|
|
45454
|
+
applyCenterOffset(target) {
|
|
45455
|
+
this.x = target - this.onTimeX;
|
|
45456
|
+
}
|
|
45402
45457
|
}
|
|
45403
45458
|
/**
|
|
45404
45459
|
* @internal
|
|
@@ -45502,13 +45557,28 @@ class BeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
45502
45557
|
this.preNotes.renderer = this.renderer;
|
|
45503
45558
|
this.preNotes.container = this;
|
|
45504
45559
|
this.preNotes.doLayout();
|
|
45505
|
-
this.
|
|
45560
|
+
this._layoutOnsetX();
|
|
45506
45561
|
this.onNotes.renderer = this.renderer;
|
|
45507
45562
|
this.onNotes.container = this;
|
|
45508
45563
|
this.onNotes.doLayout();
|
|
45509
45564
|
this.createBeatTies();
|
|
45510
45565
|
this.updateWidth();
|
|
45511
45566
|
}
|
|
45567
|
+
/**
|
|
45568
|
+
* Resets `preNotes.x`/`onNotes.x` to their natural (un-centered) baseline.
|
|
45569
|
+
* Shared by {@link doLayout} and {@link applyCenterOffset} so the latter can be called
|
|
45570
|
+
* repeatedly (once per `_scaleToForce` pass) without compounding a previous offset.
|
|
45571
|
+
*/
|
|
45572
|
+
_layoutOnsetX() {
|
|
45573
|
+
this.preNotes.x = 0;
|
|
45574
|
+
this.onNotes.x = this.preNotes.x + this.preNotes.width;
|
|
45575
|
+
}
|
|
45576
|
+
applyCenterOffset(target) {
|
|
45577
|
+
this._layoutOnsetX();
|
|
45578
|
+
const offset = target - this.onTimeX;
|
|
45579
|
+
this.preNotes.x = offset;
|
|
45580
|
+
this.onNotes.x = this.preNotes.x + this.preNotes.width;
|
|
45581
|
+
}
|
|
45512
45582
|
createBeatTies() {
|
|
45513
45583
|
let i = this.beat.notes.length - 1;
|
|
45514
45584
|
while (i >= 0) this.createTies(this.beat.notes[i--]);
|
|
@@ -48130,6 +48200,7 @@ class AlphaTabApiBase {
|
|
|
48130
48200
|
if (currentHandler !== void 0 && this._cursorHandlerMode === cursorHandlerMode) return;
|
|
48131
48201
|
if (cursorHandlerMode) this._defaultCursorHandler = new ToNextBeatAnimatingCursorHandler();
|
|
48132
48202
|
else this._defaultCursorHandler = new NonAnimatingCursorHandler();
|
|
48203
|
+
this._cursorHandlerMode = cursorHandlerMode;
|
|
48133
48204
|
}
|
|
48134
48205
|
_scrollHandlerMode = ScrollMode.Off;
|
|
48135
48206
|
_scrollHandlerVertical = true;
|
|
@@ -48259,10 +48330,8 @@ class AlphaTabApiBase {
|
|
|
48259
48330
|
shouldScroll = !stop;
|
|
48260
48331
|
shouldNotifyBeatChange = true;
|
|
48261
48332
|
}
|
|
48262
|
-
|
|
48263
|
-
|
|
48264
|
-
if (handler) handler.onBeatCursorUpdating(beatBoundings, nextBeatBoundings === null ? void 0 : nextBeatBoundings, cursorMode, startBeatX, nextBeatX, duration);
|
|
48265
|
-
}
|
|
48333
|
+
const handler = this.customScrollHandler ?? this._defaultScrollHandler;
|
|
48334
|
+
if (shouldScroll && !this._isBeatMouseDown && handler) handler.onBeatCursorUpdating(beatBoundings, nextBeatBoundings === null ? void 0 : nextBeatBoundings, cursorMode, startBeatX, nextBeatX, duration);
|
|
48266
48335
|
if (shouldNotifyBeatChange) {
|
|
48267
48336
|
this._onPlayedBeatChanged(beat);
|
|
48268
48337
|
this._onActiveBeatsChanged(new ActiveBeatsChangedEventArgs(beatsToHighlight.map((i) => i.beat)));
|
|
@@ -48598,7 +48667,7 @@ class AlphaTabApiBase {
|
|
|
48598
48667
|
}
|
|
48599
48668
|
_onBeatMouseDown(originalEvent, beat) {
|
|
48600
48669
|
if (this._isDestroyed) return;
|
|
48601
|
-
if (this._hasCursor && this.settings.player.
|
|
48670
|
+
if (this._hasCursor && this.settings.player.enablePlaybackRangeSelection) {
|
|
48602
48671
|
this._selectionStart = { beat };
|
|
48603
48672
|
this._selectionEnd = void 0;
|
|
48604
48673
|
}
|
|
@@ -48614,10 +48683,12 @@ class AlphaTabApiBase {
|
|
|
48614
48683
|
}
|
|
48615
48684
|
_onBeatMouseMove(originalEvent, beat) {
|
|
48616
48685
|
if (this._isDestroyed) return;
|
|
48617
|
-
if (this.settings.player.
|
|
48686
|
+
if (this.settings.player.enablePlaybackRangeSelection) {
|
|
48618
48687
|
if (!this._selectionEnd || this._selectionEnd.beat !== beat) {
|
|
48619
|
-
this.
|
|
48620
|
-
|
|
48688
|
+
if (this._selectionStart?.beat !== beat) {
|
|
48689
|
+
this._selectionEnd = { beat };
|
|
48690
|
+
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
48691
|
+
}
|
|
48621
48692
|
}
|
|
48622
48693
|
}
|
|
48623
48694
|
this.beatMouseMove.trigger(beat);
|
|
@@ -48630,11 +48701,30 @@ class AlphaTabApiBase {
|
|
|
48630
48701
|
}
|
|
48631
48702
|
_onBeatMouseUp(originalEvent, beat) {
|
|
48632
48703
|
if (this._isDestroyed) return;
|
|
48633
|
-
if (this._hasCursor
|
|
48704
|
+
if (this._hasCursor) {
|
|
48705
|
+
let shouldSeekToBeat = beat && this.settings.player.enableSeekToClick;
|
|
48706
|
+
if (this.settings.player.enablePlaybackRangeSelection) {
|
|
48707
|
+
if (this._internalApplyPlaybackRangeFromHighlight()) shouldSeekToBeat = false;
|
|
48708
|
+
}
|
|
48709
|
+
if (shouldSeekToBeat) this._seekToBeat(beat);
|
|
48710
|
+
}
|
|
48634
48711
|
this.beatMouseUp.trigger(beat);
|
|
48635
48712
|
this.uiFacade.triggerEvent(this.container, "beatMouseUp", beat, originalEvent);
|
|
48636
48713
|
this._isBeatMouseDown = false;
|
|
48637
48714
|
}
|
|
48715
|
+
_seekToBeat(beat) {
|
|
48716
|
+
const tickCache = this._tickCache;
|
|
48717
|
+
if (!tickCache) return;
|
|
48718
|
+
this._currentBeat = null;
|
|
48719
|
+
let beatTick = tickCache.getMasterBarStart(beat.voice.bar.masterBar) + (tickCache.getRelativeBeatPlaybackRange(beat)?.startTick ?? beat.playbackStart);
|
|
48720
|
+
const playbackRange = this.playbackRange;
|
|
48721
|
+
if (playbackRange) {
|
|
48722
|
+
if (beatTick < playbackRange.startTick) beatTick = playbackRange.startTick;
|
|
48723
|
+
else if (beatTick > playbackRange.endTick) beatTick = playbackRange.endTick;
|
|
48724
|
+
}
|
|
48725
|
+
if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(beatTick, false, 1);
|
|
48726
|
+
this.tickPosition = beatTick;
|
|
48727
|
+
}
|
|
48638
48728
|
_onNoteMouseUp(originalEvent, note) {
|
|
48639
48729
|
if (this._isDestroyed) return;
|
|
48640
48730
|
this.noteMouseUp.trigger(note);
|
|
@@ -48656,7 +48746,7 @@ class AlphaTabApiBase {
|
|
|
48656
48746
|
_setupClickHandling() {
|
|
48657
48747
|
this.canvasElement.mouseDown.on((e) => {
|
|
48658
48748
|
if (!e.isLeftMouseButton) return;
|
|
48659
|
-
if (this.settings.player.
|
|
48749
|
+
if (this.settings.player.enablePlaybackRangeSelection || this.settings.player.enableSeekToClick) e.preventDefault();
|
|
48660
48750
|
const relX = e.getX(this.canvasElement);
|
|
48661
48751
|
const relY = e.getY(this.canvasElement);
|
|
48662
48752
|
const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
|
|
@@ -48683,7 +48773,7 @@ class AlphaTabApiBase {
|
|
|
48683
48773
|
});
|
|
48684
48774
|
this.canvasElement.mouseUp.on((e) => {
|
|
48685
48775
|
if (!this._isBeatMouseDown) return;
|
|
48686
|
-
if (this.settings.player.
|
|
48776
|
+
if (this.settings.player.enablePlaybackRangeSelection || this.settings.player.enableSeekToClick) e.preventDefault();
|
|
48687
48777
|
const relX = e.getX(this.canvasElement);
|
|
48688
48778
|
const relY = e.getY(this.canvasElement);
|
|
48689
48779
|
const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
|
|
@@ -48694,7 +48784,7 @@ class AlphaTabApiBase {
|
|
|
48694
48784
|
} else this._onNoteMouseUp(e, null);
|
|
48695
48785
|
});
|
|
48696
48786
|
this._renderer.postRenderFinished.on(() => {
|
|
48697
|
-
if (!this._selectionStart || !this._hasCursor || !this.settings.player.
|
|
48787
|
+
if (!this._selectionStart || !this._hasCursor || !this.settings.player.enablePlaybackRangeSelection) return;
|
|
48698
48788
|
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
48699
48789
|
});
|
|
48700
48790
|
}
|
|
@@ -48786,6 +48876,9 @@ class AlphaTabApiBase {
|
|
|
48786
48876
|
* ```
|
|
48787
48877
|
*/
|
|
48788
48878
|
applyPlaybackRangeFromHighlight() {
|
|
48879
|
+
this._internalApplyPlaybackRangeFromHighlight();
|
|
48880
|
+
}
|
|
48881
|
+
_internalApplyPlaybackRangeFromHighlight() {
|
|
48789
48882
|
if (this._selectionEnd) {
|
|
48790
48883
|
const startTick = this._tickCache?.getBeatStart(this._selectionStart.beat) ?? this._selectionStart.beat.absolutePlaybackStart;
|
|
48791
48884
|
if ((this._tickCache?.getBeatStart(this._selectionEnd.beat) ?? this._selectionEnd.beat.absolutePlaybackStart) < startTick) {
|
|
@@ -48793,27 +48886,32 @@ class AlphaTabApiBase {
|
|
|
48793
48886
|
this._selectionStart = this._selectionEnd;
|
|
48794
48887
|
this._selectionEnd = t;
|
|
48795
48888
|
}
|
|
48796
|
-
}
|
|
48889
|
+
} else if (!this.settings.player.resetPlaybackRangeOnClick) return false;
|
|
48797
48890
|
if (this._selectionStart && this._tickCache) {
|
|
48798
48891
|
const tickCache = this._tickCache;
|
|
48799
48892
|
const realStartMasterBarStart = tickCache.getMasterBarStart(this._selectionStart.beat.voice.bar.masterBar);
|
|
48800
48893
|
const startBeatPlaybackStart = tickCache.getRelativeBeatPlaybackRange(this._selectionStart.beat)?.startTick ?? this._selectionStart.beat.playbackStart;
|
|
48801
|
-
|
|
48802
|
-
if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(realStartMasterBarStart + startBeatPlaybackStart, false, 1);
|
|
48803
|
-
this.tickPosition = realStartMasterBarStart + startBeatPlaybackStart;
|
|
48894
|
+
let seekToStart = this.settings.player.enableSeekToClick;
|
|
48804
48895
|
if (this._selectionEnd && this._selectionStart.beat !== this._selectionEnd.beat) {
|
|
48896
|
+
seekToStart = true;
|
|
48805
48897
|
const realEndMasterBarStart = tickCache.getMasterBarStart(this._selectionEnd.beat.voice.bar.masterBar);
|
|
48806
48898
|
const endBeatPlaybackEnd = tickCache.getRelativeBeatPlaybackRange(this._selectionEnd.beat)?.endTick ?? this._selectionEnd.beat.playbackStart + this._selectionEnd.beat.playbackDuration;
|
|
48807
48899
|
const range = new PlaybackRange();
|
|
48808
48900
|
range.startTick = realStartMasterBarStart + startBeatPlaybackStart;
|
|
48809
48901
|
range.endTick = realEndMasterBarStart + endBeatPlaybackEnd - 50;
|
|
48810
48902
|
this.playbackRange = range;
|
|
48811
|
-
} else {
|
|
48903
|
+
} else if (this.settings.player.resetPlaybackRangeOnClick) {
|
|
48812
48904
|
this._selectionStart = void 0;
|
|
48813
48905
|
this.playbackRange = null;
|
|
48814
48906
|
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
48815
48907
|
}
|
|
48908
|
+
if (seekToStart) {
|
|
48909
|
+
this._currentBeat = null;
|
|
48910
|
+
if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(realStartMasterBarStart + startBeatPlaybackStart, false, 1);
|
|
48911
|
+
this.tickPosition = realStartMasterBarStart + startBeatPlaybackStart;
|
|
48912
|
+
}
|
|
48816
48913
|
}
|
|
48914
|
+
return true;
|
|
48817
48915
|
}
|
|
48818
48916
|
/**
|
|
48819
48917
|
* Clears the highlight markers marking the currently selected playback range.
|
|
@@ -50099,7 +50197,8 @@ class AlphaTabApi extends AlphaTabApiBase {
|
|
|
50099
50197
|
settings.player.enableCursor = false;
|
|
50100
50198
|
settings.player.playerMode = PlayerMode.Disabled;
|
|
50101
50199
|
settings.player.enableElementHighlighting = false;
|
|
50102
|
-
settings.player.
|
|
50200
|
+
settings.player.enableSeekToClick = false;
|
|
50201
|
+
settings.player.enablePlaybackRangeSelection = false;
|
|
50103
50202
|
settings.player.soundFont = null;
|
|
50104
50203
|
settings.display.scale = .8;
|
|
50105
50204
|
settings.display.stretchForce = .8;
|
|
@@ -50909,7 +51008,9 @@ class AlphaSynthWebWorker {
|
|
|
50909
51008
|
}
|
|
50910
51009
|
handleMessage(e) {
|
|
50911
51010
|
const data = e.data;
|
|
50912
|
-
|
|
51011
|
+
const cmd = data.cmd;
|
|
51012
|
+
if (!cmd) return;
|
|
51013
|
+
switch (cmd) {
|
|
50913
51014
|
case "alphaSynth.initialize":
|
|
50914
51015
|
AlphaSynthWorkerSynthOutput.preferredSampleRate = data.sampleRate;
|
|
50915
51016
|
Logger.logLevel = data.logLevel;
|
|
@@ -51003,7 +51104,7 @@ class AlphaSynthWebWorker {
|
|
|
51003
51104
|
this._player.applyTranspositionPitches(data.transpositionPitches);
|
|
51004
51105
|
break;
|
|
51005
51106
|
}
|
|
51006
|
-
if (
|
|
51107
|
+
if (cmd.startsWith("alphaSynth.exporter")) this._handleExporterMessage(e);
|
|
51007
51108
|
}
|
|
51008
51109
|
_handleExporterMessage(ev) {
|
|
51009
51110
|
const data = ev.data;
|
|
@@ -54507,9 +54608,35 @@ class MultiVoiceContainerGlyph extends Glyph {
|
|
|
54507
54608
|
const force = this.renderer.layoutingInfo.spaceToForce(width);
|
|
54508
54609
|
this._scaleToForce(force, true);
|
|
54509
54610
|
}
|
|
54611
|
+
/**
|
|
54612
|
+
* `true` when every voice/track/staff contributes exactly one beat, of uniform duration,
|
|
54613
|
+
* spanning the bar's entire duration - i.e. a single full-bar note/rest. Common engraving
|
|
54614
|
+
* practice centers such notes horizontally within the bar rather than anchoring them right
|
|
54615
|
+
* after the pre-beat content (Behind Bars, p. 41; see #2464).
|
|
54616
|
+
*/
|
|
54617
|
+
_isCenteredFullBar() {
|
|
54618
|
+
const masterBar = this.renderer.bar.masterBar;
|
|
54619
|
+
const layoutingInfo = this.renderer.layoutingInfo;
|
|
54620
|
+
const springs = layoutingInfo.springs;
|
|
54621
|
+
if (springs.size !== 1 || !springs.has(masterBar.start) || layoutingInfo.allGraceRods.size > 0) return false;
|
|
54622
|
+
const spring = springs.get(masterBar.start);
|
|
54623
|
+
return spring.allDurations.size === 1 && spring.longestDuration === masterBar.calculateDuration();
|
|
54624
|
+
}
|
|
54510
54625
|
/** `emit=false`: positioning-only path; final skyline emission runs later via {@link scaleToWidth}. */
|
|
54511
54626
|
_scaleToForce(force, emit) {
|
|
54512
54627
|
this.width = this.renderer.layoutingInfo.calculateVoiceWidth(force);
|
|
54628
|
+
if (this._isCenteredFullBar()) {
|
|
54629
|
+
const barNumberWidth = this.renderer.barNumberWidth;
|
|
54630
|
+
const target = (this.width - barNumberWidth) / 2;
|
|
54631
|
+
for (const beatGlyphs of this.beatGlyphs.values()) {
|
|
54632
|
+
const soleBeatGlyph = beatGlyphs[0];
|
|
54633
|
+
soleBeatGlyph.x = 0;
|
|
54634
|
+
soleBeatGlyph.applyCenterOffset(target);
|
|
54635
|
+
soleBeatGlyph.scaleToWidth(this.width);
|
|
54636
|
+
if (emit) this._emitBeatContainerSkyline(soleBeatGlyph);
|
|
54637
|
+
}
|
|
54638
|
+
return;
|
|
54639
|
+
}
|
|
54513
54640
|
const positions = this.renderer.layoutingInfo.buildOnTimePositions(force);
|
|
54514
54641
|
for (const beatGlyphs of this.beatGlyphs.values()) for (let i = 0, j = beatGlyphs.length; i < j; i++) {
|
|
54515
54642
|
const currentBeatGlyph = beatGlyphs[i];
|
|
@@ -60831,14 +60958,22 @@ class LineBarRenderer extends BarRendererBase {
|
|
|
60831
60958
|
calculateBeamY(h, x) {
|
|
60832
60959
|
return this.calculateBeamYWithDirection(h, x, this.getBeamDirection(h));
|
|
60833
60960
|
}
|
|
60961
|
+
barNumberGlyph;
|
|
60962
|
+
get barNumberWidth() {
|
|
60963
|
+
return this.barNumberGlyph?.width ?? 0;
|
|
60964
|
+
}
|
|
60834
60965
|
createPreBeatGlyphs() {
|
|
60835
60966
|
super.createPreBeatGlyphs();
|
|
60967
|
+
this.barNumberGlyph = void 0;
|
|
60836
60968
|
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
60837
60969
|
this.createLinePreBeatGlyphs();
|
|
60838
60970
|
let hasSpaceAfterStartGlyphs = false;
|
|
60839
60971
|
if (this.index === 0) hasSpaceAfterStartGlyphs = this.createStartSpacing();
|
|
60840
|
-
if (this.shouldCreateBarNumber())
|
|
60841
|
-
|
|
60972
|
+
if (this.shouldCreateBarNumber()) {
|
|
60973
|
+
const barNumberGlyph = new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1);
|
|
60974
|
+
this.barNumberGlyph = barNumberGlyph;
|
|
60975
|
+
this.addPreBeatGlyph(barNumberGlyph);
|
|
60976
|
+
} else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
60842
60977
|
}
|
|
60843
60978
|
resolveClefDisplay() {
|
|
60844
60979
|
return { isVisible: false };
|
|
@@ -64430,8 +64565,11 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
64430
64565
|
if (this.index === 0 || this.bar.masterBar.isRepeatStart && this.staff.isCascadePrimary) this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
64431
64566
|
this.createLinePreBeatGlyphs();
|
|
64432
64567
|
const hasSpaceAfterStartGlyphs = this.createStartSpacing();
|
|
64433
|
-
if (this.shouldCreateBarNumber())
|
|
64434
|
-
|
|
64568
|
+
if (this.shouldCreateBarNumber()) {
|
|
64569
|
+
const barNumberGlyph = new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1);
|
|
64570
|
+
this.barNumberGlyph = barNumberGlyph;
|
|
64571
|
+
this.addPreBeatGlyph(barNumberGlyph);
|
|
64572
|
+
} else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
64435
64573
|
}
|
|
64436
64574
|
createLinePreBeatGlyphs() {
|
|
64437
64575
|
const timeSignatureDisplay = this.resolveTimeSignatureDisplay();
|
package/dist/alphaTab.d.ts
CHANGED
|
@@ -2083,6 +2083,7 @@ export declare class AlphaTabApiBase<TSettings> {
|
|
|
2083
2083
|
private _onBeatMouseMove;
|
|
2084
2084
|
private _onNoteMouseMove;
|
|
2085
2085
|
private _onBeatMouseUp;
|
|
2086
|
+
private _seekToBeat;
|
|
2086
2087
|
private _onNoteMouseUp;
|
|
2087
2088
|
private _updateSelectionCursor;
|
|
2088
2089
|
private _setupClickHandling;
|
|
@@ -2170,6 +2171,7 @@ export declare class AlphaTabApiBase<TSettings> {
|
|
|
2170
2171
|
* ```
|
|
2171
2172
|
*/
|
|
2172
2173
|
applyPlaybackRangeFromHighlight(): void;
|
|
2174
|
+
private _internalApplyPlaybackRangeFromHighlight;
|
|
2173
2175
|
/**
|
|
2174
2176
|
* Clears the highlight markers marking the currently selected playback range.
|
|
2175
2177
|
*
|
|
@@ -3234,6 +3236,7 @@ export declare namespace alphaTex {
|
|
|
3234
3236
|
IAlphaTexAstNode,
|
|
3235
3237
|
IAlphaTexMetaDataTagPrefixNode,
|
|
3236
3238
|
IAlphaTexNoteValueNode,
|
|
3239
|
+
IAlphaTexStringSeparatorNode,
|
|
3237
3240
|
AlphaTexLexer,
|
|
3238
3241
|
AlphaTexParseMode,
|
|
3239
3242
|
AlphaTexParser,
|
|
@@ -9545,7 +9548,7 @@ declare interface IContainer {
|
|
|
9545
9548
|
*
|
|
9546
9549
|
* @public
|
|
9547
9550
|
*/
|
|
9548
|
-
declare interface ICursorHandler {
|
|
9551
|
+
export declare interface ICursorHandler {
|
|
9549
9552
|
/**
|
|
9550
9553
|
* Called when this handler activates. This can be on dynamic cursor creation
|
|
9551
9554
|
* or when setting a custom handler with cursors already created.
|
|
@@ -13996,11 +13999,39 @@ export declare class PlayerSettings {
|
|
|
13996
13999
|
* @since 0.9.7
|
|
13997
14000
|
* @defaultValue `true`
|
|
13998
14001
|
* @category Player
|
|
14002
|
+
* @json_read_only
|
|
13999
14003
|
* @remarks
|
|
14000
14004
|
* This setting configures whether alphaTab provides the default user interaction features like selection of the playback range and "seek on click".
|
|
14001
14005
|
* By default users can select the desired playback range with the mouse and also jump to individual beats by click. This behavior can be contolled with this setting.
|
|
14006
|
+
* @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
|
|
14007
|
+
*/
|
|
14008
|
+
get enableUserInteraction(): boolean;
|
|
14009
|
+
/**
|
|
14010
|
+
* @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
|
|
14011
|
+
*/
|
|
14012
|
+
set enableUserInteraction(value: boolean);
|
|
14013
|
+
/**
|
|
14014
|
+
* Whether the a click on the music sheet triggers a player seek to the note/beat at the
|
|
14015
|
+
* clicked location.
|
|
14016
|
+
* @since 1.9.0
|
|
14017
|
+
* @defaultValue `true`
|
|
14018
|
+
* @category Player
|
|
14019
|
+
*/
|
|
14020
|
+
enableSeekToClick: boolean;
|
|
14021
|
+
/**
|
|
14022
|
+
* Whether user click and drag results in a selection defining the playback range.
|
|
14023
|
+
* @since 1.9.0
|
|
14024
|
+
* @defaultValue `true`
|
|
14025
|
+
* @category Player
|
|
14026
|
+
*/
|
|
14027
|
+
enablePlaybackRangeSelection: boolean;
|
|
14028
|
+
/**
|
|
14029
|
+
* Whether a simple click (no range drag) should reset the current playback range.
|
|
14030
|
+
* @since 1.9.0
|
|
14031
|
+
* @defaultValue `true`
|
|
14032
|
+
* @category Player
|
|
14002
14033
|
*/
|
|
14003
|
-
|
|
14034
|
+
resetPlaybackRangeOnClick: boolean;
|
|
14004
14035
|
/**
|
|
14005
14036
|
* The X-offset to add when scrolling.
|
|
14006
14037
|
* @since 0.9.6
|
|
@@ -14268,11 +14299,35 @@ declare interface PlayerSettingsJson {
|
|
|
14268
14299
|
* @since 0.9.7
|
|
14269
14300
|
* @defaultValue `true`
|
|
14270
14301
|
* @category Player
|
|
14302
|
+
* @json_read_only
|
|
14271
14303
|
* @remarks
|
|
14272
14304
|
* This setting configures whether alphaTab provides the default user interaction features like selection of the playback range and "seek on click".
|
|
14273
14305
|
* By default users can select the desired playback range with the mouse and also jump to individual beats by click. This behavior can be contolled with this setting.
|
|
14306
|
+
* @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
|
|
14274
14307
|
*/
|
|
14275
14308
|
enableUserInteraction?: boolean;
|
|
14309
|
+
/**
|
|
14310
|
+
* Whether the a click on the music sheet triggers a player seek to the note/beat at the
|
|
14311
|
+
* clicked location.
|
|
14312
|
+
* @since 1.9.0
|
|
14313
|
+
* @defaultValue `true`
|
|
14314
|
+
* @category Player
|
|
14315
|
+
*/
|
|
14316
|
+
enableSeekToClick?: boolean;
|
|
14317
|
+
/**
|
|
14318
|
+
* Whether user click and drag results in a selection defining the playback range.
|
|
14319
|
+
* @since 1.9.0
|
|
14320
|
+
* @defaultValue `true`
|
|
14321
|
+
* @category Player
|
|
14322
|
+
*/
|
|
14323
|
+
enablePlaybackRangeSelection?: boolean;
|
|
14324
|
+
/**
|
|
14325
|
+
* Whether a simple click (no range drag) should reset the current playback range.
|
|
14326
|
+
* @since 1.9.0
|
|
14327
|
+
* @defaultValue `true`
|
|
14328
|
+
* @category Player
|
|
14329
|
+
*/
|
|
14330
|
+
resetPlaybackRangeOnClick?: boolean;
|
|
14276
14331
|
/**
|
|
14277
14332
|
* The X-offset to add when scrolling.
|
|
14278
14333
|
* @since 0.9.6
|