@laplace.live/pixijs-live2d 0.5.0 → 0.6.0

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/index.d.ts CHANGED
@@ -3337,6 +3337,11 @@ export declare abstract class MotionManager<Motion = unknown, MotionSpec = unkno
3337
3337
  * is dropped; a higher-priority motion in flight hands over to the new selection when it ends.
3338
3338
  */
3339
3339
  setIdleMotion(motion: IdleMotion): void;
3340
+ /**
3341
+ * List a motion file after load, under `group`, so a file written beside the model plays
3342
+ * without a reload. A new group is created; an existing one grows by one index.
3343
+ */
3344
+ addMotion(group: string, definition: MotionSpec): void;
3340
3345
  /** Stop the idle so the next update starts the selection. Cubism eases its parameters home too. */
3341
3346
  protected releaseIdle(): void;
3342
3347
  /** Start the idle selection at IDLE priority; a chosen motion loops regardless of its own flag. */
@@ -3560,7 +3565,9 @@ export declare abstract class ExpressionManager<Expression = unknown, Expression
3560
3565
  */
3561
3566
  tag: string;
3562
3567
  /**
3563
- * Expression definitions copied from ModelSettings.
3568
+ * Expression definitions copied from ModelSettings. An index is not stable across an `await`:
3569
+ * {@link removeDefinition} shifts the ones above it, so a load or activation in flight
3570
+ * re-resolves its definition afterwards rather than trusting the index it started with.
3564
3571
  */
3565
3572
  abstract readonly definitions: ExpressionSpec[];
3566
3573
  /**
@@ -3593,6 +3600,14 @@ export declare abstract class ExpressionManager<Expression = unknown, Expression
3593
3600
  * Active set remembered by {@link resetExpression} for {@link restoreExpression}.
3594
3601
  */
3595
3602
  protected suppressedIndices: number[] | null;
3603
+ /**
3604
+ * Indices whose parameters are skipped while they stay active — an editor previewing an
3605
+ * expression's own edit needs the real one silent without touching the active set anyone
3606
+ * persists or observes.
3607
+ */
3608
+ protected muted: Set<number>;
3609
+ /** Every entry silenced at once (the editor's Solo), on top of {@link muted}. */
3610
+ protected muteAll: boolean;
3596
3611
  /**
3597
3612
  * Flags the instance has been destroyed.
3598
3613
  */
@@ -3612,6 +3627,40 @@ export declare abstract class ExpressionManager<Expression = unknown, Expression
3612
3627
  * @ignore
3613
3628
  */
3614
3629
  private _loadExpression;
3630
+ /**
3631
+ * Lists a definition after load, so a file written beside the model activates without a reload.
3632
+ * @return The new index.
3633
+ */
3634
+ addDefinition(definition: ExpressionSpec): number;
3635
+ /**
3636
+ * Replaces the loaded Expression at `index` — a file the editor just rewrote — keeping an active one
3637
+ * active at its current weight.
3638
+ */
3639
+ replaceExpression(index: number, expression: Expression): void;
3640
+ /**
3641
+ * Forgets a definition (its file was deleted or renamed away): deactivates it, then shifts every
3642
+ * index above it so the remaining expressions keep their state. An activation of it still loading
3643
+ * settles as a no-op.
3644
+ */
3645
+ removeDefinition(index: number): void;
3646
+ /**
3647
+ * Mutes or unmutes an Expression: an active one keeps its state and fade but contributes nothing
3648
+ * until unmuted. Unknown indices are ignored.
3649
+ */
3650
+ setExpressionMuted(index: number | string, muted: boolean): void;
3651
+ /**
3652
+ * Mutes or unmutes every Expression at once, active state untouched; the per-entry mutes stay
3653
+ * as they are underneath.
3654
+ */
3655
+ setAllMuted(muted: boolean): void;
3656
+ /**
3657
+ * A loaded Expression was swapped for another at `index`; a subclass holding it live re-points.
3658
+ */
3659
+ protected onExpressionReplaced(_index: number, _expression: Expression): void;
3660
+ /**
3661
+ * The definition at `index` is gone and every index above it moved down by one.
3662
+ */
3663
+ protected onDefinitionRemoved(_index: number): void;
3615
3664
  /**
3616
3665
  * Activates a random inactive Expression.
3617
3666
  * @return Promise that resolves with true if succeeded, with false otherwise.
@@ -4675,7 +4724,8 @@ export declare class Live2DFactory {
4675
4724
  /**
4676
4725
  * Load tasks of each expression.
4677
4726
  */
4678
- static expressionTasksMap: WeakMap<ExpressionManager<unknown, unknown>, (Promise<any> | undefined)[]>;
4727
+ /** Keyed by the definition object: a removal shifts indices, never the object. */
4728
+ static expressionTasksMap: WeakMap<ExpressionManager<unknown, unknown>, Map<unknown, Promise<any>>>;
4679
4729
  /**
4680
4730
  * Registers a Live2DRuntime.
4681
4731
  */
@@ -5761,9 +5811,15 @@ export declare class CubismModelSettings extends ModelSettings {
5761
5811
  export declare class CubismExpressionManager extends ExpressionManager<CubismExpressionMotion, Expression> {
5762
5812
  readonly expressionDataType: "arraybuffer";
5763
5813
  readonly definitions: Expression[];
5814
+ /** The settings the listings read; `definitions` was filtered out of them, so both are kept in step. */
5815
+ private readonly cubismSettings;
5764
5816
  /** Active fade entries in activation order; deactivated ones stay until fully faded out. */
5765
5817
  private entries;
5766
5818
  constructor(settings: CubismModelSettings, options?: MotionManagerOptions);
5819
+ addDefinition(definition: Expression): number;
5820
+ removeDefinition(index: number): void;
5821
+ protected onExpressionReplaced(index: number, expression: CubismExpressionMotion): void;
5822
+ protected onDefinitionRemoved(index: number): void;
5767
5823
  isFinished(): boolean;
5768
5824
  getExpressionIndex(name: string): number;
5769
5825
  getExpressionFile(definition: Expression): string;
@@ -6945,6 +7001,12 @@ export declare class CubismMotionManager extends MotionManager<CubismMotion, Mot
6945
7001
  isFinished(): boolean;
6946
7002
  protected _startMotion(motion: CubismMotion, onFinish?: (motion: CubismMotion) => void, ignoreParamIds?: string[], loop?: boolean): number;
6947
7003
  protected _stopAllMotions(): void;
7004
+ /**
7005
+ * Fade the queue's motions out over their own fade-out time instead of cutting them; each
7006
+ * ends like a natural finish (idle restart, `motionFinish`), which is how a looping one stops.
7007
+ * The motion's sound stops at once, as it does on {@link stopAllMotions}.
7008
+ */
7009
+ fadeOutMotions(): void;
6948
7010
  createMotion(data: ArrayBuffer, group: string, definition: Motion): CubismMotion;
6949
7011
  getMotionFile(definition: Motion): string;
6950
7012
  protected getMotionName(definition: Motion): string;
@@ -6953,6 +7015,13 @@ export declare class CubismMotionManager extends MotionManager<CubismMotion, Mot
6953
7015
  currentMotionBlinks(): boolean;
6954
7016
  /** The parameters the playing motion writes, for a host driver handing them over to it; null when none plays. */
6955
7017
  currentMotionParameters(): ReadonlySet<string> | null;
7018
+ /**
7019
+ * The parameters a playing one-shot (anything above IDLE) writes — what a host's tracking
7020
+ * yields to while it plays, as VTS ranks an animation above tracking. Null under the idle.
7021
+ */
7022
+ oneShotParameters(): ReadonlySet<string> | null;
7023
+ /** A motion above idle priority is current — one the player started, never the idle. */
7024
+ oneShotPlaying(): boolean;
6956
7025
  private currentMotion;
6957
7026
  private currentMeta;
6958
7027
  protected releaseIdle(): void;
package/dist/index.js CHANGED
@@ -2734,6 +2734,14 @@ var ExpressionManager = class extends EventEmitter {
2734
2734
  */
2735
2735
  suppressedIndices = null;
2736
2736
  /**
2737
+ * Indices whose parameters are skipped while they stay active — an editor previewing an
2738
+ * expression's own edit needs the real one silent without touching the active set anyone
2739
+ * persists or observes.
2740
+ */
2741
+ muted = /* @__PURE__ */ new Set();
2742
+ /** Every entry silenced at once (the editor's Solo), on top of {@link muted}. */
2743
+ muteAll = false;
2744
+ /**
2737
2745
  * Flags the instance has been destroyed.
2738
2746
  */
2739
2747
  destroyed = false;
@@ -2751,7 +2759,8 @@ var ExpressionManager = class extends EventEmitter {
2751
2759
  * @emits {@link ExpressionManagerEvents.expressionLoadError}
2752
2760
  */
2753
2761
  async loadExpression(index) {
2754
- if (!this.definitions[index]) {
2762
+ const definition = this.definitions[index];
2763
+ if (!definition) {
2755
2764
  logger.warn(this.tag, `Undefined expression at [${index}]`);
2756
2765
  return;
2757
2766
  }
@@ -2762,7 +2771,11 @@ var ExpressionManager = class extends EventEmitter {
2762
2771
  if (this.expressions[index]) return this.expressions[index];
2763
2772
  const expression = await this._loadExpression(index);
2764
2773
  if (this.destroyed) return;
2765
- this.expressions[index] = expression;
2774
+ const slot = this.definitions.indexOf(definition);
2775
+ if (slot < 0) return;
2776
+ const replaced = this.expressions[slot];
2777
+ if (replaced) return replaced;
2778
+ this.expressions[slot] = expression;
2766
2779
  return expression;
2767
2780
  }
2768
2781
  /**
@@ -2773,6 +2786,66 @@ var ExpressionManager = class extends EventEmitter {
2773
2786
  throw new Error("Not implemented.");
2774
2787
  }
2775
2788
  /**
2789
+ * Lists a definition after load, so a file written beside the model activates without a reload.
2790
+ * @return The new index.
2791
+ */
2792
+ addDefinition(definition) {
2793
+ this.definitions.push(definition);
2794
+ return this.definitions.length - 1;
2795
+ }
2796
+ /**
2797
+ * Replaces the loaded Expression at `index` — a file the editor just rewrote — keeping an active one
2798
+ * active at its current weight.
2799
+ */
2800
+ replaceExpression(index, expression) {
2801
+ if (!this.definitions[index]) return;
2802
+ this.expressions[index] = expression;
2803
+ this.onExpressionReplaced(index, expression);
2804
+ }
2805
+ /**
2806
+ * Forgets a definition (its file was deleted or renamed away): deactivates it, then shifts every
2807
+ * index above it so the remaining expressions keep their state. An activation of it still loading
2808
+ * settles as a no-op.
2809
+ */
2810
+ removeDefinition(index) {
2811
+ if (!(index >= 0 && index < this.definitions.length)) return;
2812
+ this.unsetExpression(index);
2813
+ this.definitions.splice(index, 1);
2814
+ this.expressions.splice(index, 1);
2815
+ const shift = (i) => i > index ? i - 1 : i;
2816
+ this.activeIndices = this.activeIndices.map(shift);
2817
+ this.pendingIndices = new Set([...this.pendingIndices].map(shift));
2818
+ this.requestSeqs = new Map([...this.requestSeqs].map(([i, seq]) => [shift(i), seq]));
2819
+ if (this.suppressedIndices) this.suppressedIndices = this.suppressedIndices.filter((i) => i !== index).map(shift);
2820
+ this.muted = new Set([...this.muted].filter((i) => i !== index).map(shift));
2821
+ this.onDefinitionRemoved(index);
2822
+ }
2823
+ /**
2824
+ * Mutes or unmutes an Expression: an active one keeps its state and fade but contributes nothing
2825
+ * until unmuted. Unknown indices are ignored.
2826
+ */
2827
+ setExpressionMuted(index, muted) {
2828
+ if (typeof index !== "number") index = this.getExpressionIndex(index);
2829
+ if (!this.definitions[index]) return;
2830
+ if (muted) this.muted.add(index);
2831
+ else this.muted.delete(index);
2832
+ }
2833
+ /**
2834
+ * Mutes or unmutes every Expression at once, active state untouched; the per-entry mutes stay
2835
+ * as they are underneath.
2836
+ */
2837
+ setAllMuted(muted) {
2838
+ this.muteAll = muted;
2839
+ }
2840
+ /**
2841
+ * A loaded Expression was swapped for another at `index`; a subclass holding it live re-points.
2842
+ */
2843
+ onExpressionReplaced(_index, _expression) {}
2844
+ /**
2845
+ * The definition at `index` is gone and every index above it moved down by one.
2846
+ */
2847
+ onDefinitionRemoved(_index) {}
2848
+ /**
2776
2849
  * Activates a random inactive Expression.
2777
2850
  * @return Promise that resolves with true if succeeded, with false otherwise.
2778
2851
  */
@@ -2837,14 +2910,17 @@ var ExpressionManager = class extends EventEmitter {
2837
2910
  */
2838
2911
  async setExpression(index, options) {
2839
2912
  if (typeof index !== "number") index = this.getExpressionIndex(index);
2840
- if (!(index > -1 && index < this.definitions.length)) return false;
2913
+ const definition = this.definitions[index];
2914
+ if (!definition) return false;
2841
2915
  if (this.activeIndices.includes(index) || this.pendingIndices.has(index)) return false;
2842
2916
  this.pendingIndices.add(index);
2843
2917
  const seq = this.nextRequestSeq++;
2844
2918
  this.requestSeqs.set(index, seq);
2845
2919
  this.emit("expressionsChanged");
2846
2920
  const expression = await this.loadExpression(index);
2847
- if (this.destroyed || this.requestSeqs.get(index) !== seq || !this.pendingIndices.has(index)) return false;
2921
+ if (this.destroyed) return false;
2922
+ index = this.definitions.indexOf(definition);
2923
+ if (index < 0 || this.requestSeqs.get(index) !== seq || !this.pendingIndices.has(index)) return false;
2848
2924
  if (!expression) {
2849
2925
  this.pendingIndices.delete(index);
2850
2926
  this.requestSeqs.delete(index);
@@ -2911,6 +2987,8 @@ var ExpressionManager = class extends EventEmitter {
2911
2987
  this.requestSeqs.clear();
2912
2988
  this.activeIndices = [];
2913
2989
  this.suppressedIndices = null;
2990
+ this.muted.clear();
2991
+ this.muteAll = false;
2914
2992
  this.stopAllExpressions();
2915
2993
  const self = this;
2916
2994
  self.definitions = void 0;
@@ -3986,6 +4064,16 @@ var MotionManager = class extends EventEmitter {
3986
4064
  this.state.setReservedIdle(void 0, void 0);
3987
4065
  if (this.state.currentPriority === 1) this.releaseIdle();
3988
4066
  }
4067
+ /**
4068
+ * List a motion file after load, under `group`, so a file written beside the model plays
4069
+ * without a reload. A new group is created; an existing one grows by one index.
4070
+ */
4071
+ addMotion(group, definition) {
4072
+ const definitions = this.definitions[group] ?? [];
4073
+ definitions.push(definition);
4074
+ this.definitions[group] = definitions;
4075
+ this.motionGroups[group] ??= [];
4076
+ }
3989
4077
  /** Stop the idle so the next update starts the selection. Cubism eases its parameters home too. */
3990
4078
  releaseIdle() {
3991
4079
  this.stopAllMotions();
@@ -4871,6 +4959,7 @@ var Live2DFactory = class Live2DFactory {
4871
4959
  /**
4872
4960
  * Load tasks of each expression.
4873
4961
  */
4962
+ /** Keyed by the definition object: a removal shifts indices, never the object. */
4874
4963
  static expressionTasksMap = /* @__PURE__ */ new WeakMap();
4875
4964
  /**
4876
4965
  * Registers a Live2DRuntime.
@@ -4969,28 +5058,33 @@ var Live2DFactory = class Live2DFactory {
4969
5058
  expressionManager.once("destroy", () => Live2DFactory.releaseExpressionTasks(expressionManager));
4970
5059
  let tasks = Live2DFactory.expressionTasksMap.get(expressionManager);
4971
5060
  if (!tasks) {
4972
- tasks = [];
5061
+ tasks = /* @__PURE__ */ new Map();
4973
5062
  Live2DFactory.expressionTasksMap.set(expressionManager, tasks);
4974
5063
  }
4975
5064
  const path = expressionManager.getExpressionFile(definition);
4976
5065
  const responseType = expressionManager.expressionDataType ?? "json";
4977
- tasks[index] ??= Live2DLoader.load({
4978
- url: path,
4979
- settings: expressionManager.settings,
4980
- type: responseType,
4981
- target: expressionManager
4982
- }).then((data) => {
4983
- const tasks = Live2DFactory.expressionTasksMap.get(expressionManager);
4984
- if (tasks) tasks[index] = void 0;
4985
- const expressionData = data;
4986
- const expression = expressionManager.createExpression(expressionData, definition);
4987
- expressionManager.emit("expressionLoaded", index, expression);
4988
- return expression;
4989
- }).catch((e) => {
4990
- logger.warn(expressionManager.tag, `Failed to load expression: ${path}\n`, e);
4991
- handleError(e);
4992
- });
4993
- return tasks[index];
5066
+ let task = tasks.get(definition);
5067
+ if (!task) {
5068
+ task = Live2DLoader.load({
5069
+ url: path,
5070
+ settings: expressionManager.settings,
5071
+ type: responseType,
5072
+ target: expressionManager
5073
+ }).then((data) => {
5074
+ const expressionData = data;
5075
+ const expression = expressionManager.createExpression(expressionData, definition);
5076
+ const current = expressionManager.definitions.indexOf(definition);
5077
+ if (current >= 0) expressionManager.emit("expressionLoaded", current, expression);
5078
+ return expression;
5079
+ }).catch((e) => {
5080
+ logger.warn(expressionManager.tag, `Failed to load expression: ${path}\n`, e);
5081
+ handleError(e);
5082
+ }).finally(() => {
5083
+ Live2DFactory.expressionTasksMap.get(expressionManager)?.delete(definition);
5084
+ });
5085
+ tasks.set(definition, task);
5086
+ }
5087
+ return task;
4994
5088
  } catch (e) {
4995
5089
  logger.warn(expressionManager.tag, `Failed to load expression at [${index}]\n`, e);
4996
5090
  handleError(e);
@@ -14600,12 +14694,39 @@ let Live2DCubismFramework$2;
14600
14694
  var CubismExpressionManager = class extends ExpressionManager {
14601
14695
  expressionDataType = "arraybuffer";
14602
14696
  definitions;
14697
+ /** The settings the listings read; `definitions` was filtered out of them, so both are kept in step. */
14698
+ cubismSettings;
14603
14699
  /** Active fade entries in activation order; deactivated ones stay until fully faded out. */
14604
14700
  entries = [];
14605
14701
  constructor(settings, options) {
14606
14702
  super(settings, options);
14703
+ this.cubismSettings = settings;
14607
14704
  this.definitions = settings.expressions?.filter((expression) => !!expression && typeof expression.File === "string" && typeof expression.Name === "string") ?? [];
14608
14705
  }
14706
+ addDefinition(definition) {
14707
+ const index = super.addDefinition(definition);
14708
+ this.cubismSettings.expressions ??= [];
14709
+ this.cubismSettings.expressions.push(definition);
14710
+ return index;
14711
+ }
14712
+ removeDefinition(index) {
14713
+ const definition = this.definitions[index];
14714
+ super.removeDefinition(index);
14715
+ const listed = this.cubismSettings.expressions;
14716
+ const at = definition && listed ? listed.indexOf(definition) : -1;
14717
+ if (listed && at >= 0) listed.splice(at, 1);
14718
+ }
14719
+ onExpressionReplaced(index, expression) {
14720
+ for (const entry of this.entries) if (entry.index === index) {
14721
+ entry.motion = expression;
14722
+ entry.fadeStartWeight = entry.weight;
14723
+ entry.fadeStartTime = -1;
14724
+ }
14725
+ }
14726
+ onDefinitionRemoved(index) {
14727
+ this.entries = this.entries.filter((entry) => entry.index !== index);
14728
+ for (const entry of this.entries) if (entry.index > index) entry.index -= 1;
14729
+ }
14609
14730
  isFinished() {
14610
14731
  return this.entries.length === 0;
14611
14732
  }
@@ -14662,6 +14783,7 @@ var CubismExpressionManager = class extends ExpressionManager {
14662
14783
  if (!this.entries.length) return false;
14663
14784
  const states = /* @__PURE__ */ new Map();
14664
14785
  for (const entry of this.entries) {
14786
+ if (this.muteAll || this.muted.has(entry.index)) continue;
14665
14787
  const weight = entry.weight;
14666
14788
  for (const parameter of entry.motion.getExpressionParameters()) {
14667
14789
  if (parameter.parameterId == null) continue;
@@ -14730,7 +14852,8 @@ var CubismMotionManager = class extends MotionManager {
14730
14852
  release = null;
14731
14853
  constructor(parent) {
14732
14854
  super(parent);
14733
- this.definitions = parent.settings.motions ?? {};
14855
+ parent.settings.motions ??= {};
14856
+ this.definitions = parent.settings.motions;
14734
14857
  this.eyeBlinkIds = parent.settings.getEyeBlinkParameters() || [];
14735
14858
  const lipSyncIds = parent.settings.getLipSyncParameters();
14736
14859
  if (lipSyncIds?.length) this.lipSyncIds = lipSyncIds;
@@ -14738,7 +14861,7 @@ var CubismMotionManager = class extends MotionManager {
14738
14861
  }
14739
14862
  init(options) {
14740
14863
  super.init(options);
14741
- if (this.settings.expressions) this.expressionManager = new CubismExpressionManager(this.settings, options);
14864
+ this.expressionManager = new CubismExpressionManager(this.settings, options);
14742
14865
  this.queueManager.setEventCallback((_caller, eventValue) => {
14743
14866
  const value = eventValue == null ? "undefined" : String(eventValue);
14744
14867
  this.emit(`motion:${value}`);
@@ -14765,6 +14888,15 @@ var CubismMotionManager = class extends MotionManager {
14765
14888
  _stopAllMotions() {
14766
14889
  this.queueManager.stopAllMotions();
14767
14890
  }
14891
+ /**
14892
+ * Fade the queue's motions out over their own fade-out time instead of cutting them; each
14893
+ * ends like a natural finish (idle restart, `motionFinish`), which is how a looping one stops.
14894
+ * The motion's sound stops at once, as it does on {@link stopAllMotions}.
14895
+ */
14896
+ fadeOutMotions() {
14897
+ for (const entry of this.queueManager.getCubismMotionQueueEntries()) entry.setFadeOut(entry._motion.getFadeOutTime());
14898
+ this.stopSpeaking();
14899
+ }
14768
14900
  createMotion(data, group, definition) {
14769
14901
  const shouldCheckMotionConsistency = !!this.parent.options.checkMotionConsistency;
14770
14902
  const motion = CubismMotion.create(data, data.byteLength, void 0, void 0, shouldCheckMotionConsistency);
@@ -14772,8 +14904,8 @@ var CubismMotionManager = class extends MotionManager {
14772
14904
  motion.setLoop(json.isMotionLoop());
14773
14905
  this.meta.set(motion, motionMeta(motion, this.eyeBlinkIds));
14774
14906
  const defaultFadingDuration = (group === this.groups.idle ? config.idleMotionFadingDuration : config.motionFadingDuration) / 1e3;
14775
- if (json.getMotionFadeInTime() === void 0) motion.setFadeInTime(definition.FadeInTime > 0 ? definition.FadeInTime : defaultFadingDuration);
14776
- if (json.getMotionFadeOutTime() === void 0) motion.setFadeOutTime(definition.FadeOutTime > 0 ? definition.FadeOutTime : defaultFadingDuration);
14907
+ if (!json.isExistMotionFadeInTime()) motion.setFadeInTime(definition.FadeInTime > 0 ? definition.FadeInTime : defaultFadingDuration);
14908
+ if (!json.isExistMotionFadeOutTime()) motion.setFadeOutTime(definition.FadeOutTime > 0 ? definition.FadeOutTime : defaultFadingDuration);
14777
14909
  motion.setEffectIds(this.createIdList(this.eyeBlinkIds), this.createIdList(this.lipSyncIds));
14778
14910
  return motion;
14779
14911
  }
@@ -14794,6 +14926,17 @@ var CubismMotionManager = class extends MotionManager {
14794
14926
  currentMotionParameters() {
14795
14927
  return this.currentMeta()?.animated ?? null;
14796
14928
  }
14929
+ /**
14930
+ * The parameters a playing one-shot (anything above IDLE) writes — what a host's tracking
14931
+ * yields to while it plays, as VTS ranks an animation above tracking. Null under the idle.
14932
+ */
14933
+ oneShotParameters() {
14934
+ return this.oneShotPlaying() ? this.currentMotionParameters() : null;
14935
+ }
14936
+ /** A motion above idle priority is current — one the player started, never the idle. */
14937
+ oneShotPlaying() {
14938
+ return this.state.currentPriority > 1;
14939
+ }
14797
14940
  currentMotion() {
14798
14941
  const { currentGroup, currentIndex } = this.state;
14799
14942
  if (currentGroup === void 0 || currentIndex === void 0) return null;