@safe-engine/pixi 8.9.4 → 8.9.6

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.
Files changed (33) hide show
  1. package/dist/app.d.ts +1 -0
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +14 -3
  4. package/dist/spine/lib/BatchableSpineSlot.d.ts +7 -7
  5. package/dist/spine/lib/BatchableSpineSlot.js +7 -7
  6. package/dist/spine/lib/Spine.d.ts +89 -14
  7. package/dist/spine/lib/Spine.d.ts.map +1 -1
  8. package/dist/spine/lib/Spine.js +207 -42
  9. package/dist/spine/lib/SpineDebugRenderer.d.ts +7 -7
  10. package/dist/spine/lib/SpineDebugRenderer.js +7 -7
  11. package/dist/spine/lib/SpinePipe.d.ts +9 -9
  12. package/dist/spine/lib/SpinePipe.d.ts.map +1 -1
  13. package/dist/spine/lib/SpinePipe.js +17 -12
  14. package/dist/spine/lib/SpineTexture.d.ts +7 -7
  15. package/dist/spine/lib/SpineTexture.js +7 -7
  16. package/dist/spine/lib/assets/atlasLoader.d.ts +7 -7
  17. package/dist/spine/lib/assets/atlasLoader.d.ts.map +1 -1
  18. package/dist/spine/lib/assets/atlasLoader.js +16 -12
  19. package/dist/spine/lib/assets/skeletonLoader.d.ts +7 -7
  20. package/dist/spine/lib/assets/skeletonLoader.js +14 -10
  21. package/dist/spine/lib/darktint/DarkTintBatchGeometry.d.ts +6 -6
  22. package/dist/spine/lib/darktint/DarkTintBatchGeometry.js +6 -6
  23. package/dist/spine/lib/darktint/DarkTintBatcher.d.ts +6 -6
  24. package/dist/spine/lib/darktint/DarkTintBatcher.js +6 -6
  25. package/dist/spine/lib/darktint/DarkTintShader.d.ts +6 -6
  26. package/dist/spine/lib/darktint/DarkTintShader.js +6 -6
  27. package/dist/spine/lib/darktint/darkTintBit.d.ts +6 -6
  28. package/dist/spine/lib/darktint/darkTintBit.js +6 -6
  29. package/dist/spine/lib/index.d.ts +1 -1
  30. package/dist/spine/lib/index.js +1 -1
  31. package/dist/spine/lib/require-shim.d.ts +7 -7
  32. package/dist/spine/lib/require-shim.js +7 -7
  33. package/package.json +1 -1
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,14 +23,115 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
- import { AnimationState, AnimationStateData, AtlasAttachmentLoader, ClippingAttachment, Color, MeshAttachment, Physics, Pool, RegionAttachment, Skeleton, SkeletonBinary, SkeletonBounds, SkeletonClipping, SkeletonData, SkeletonJson, Vector2, } from '@esotericsoftware/spine-core';
30
- import { Assets, Cache, Container, DEG_TO_RAD, fastCopy, Graphics, Texture, Ticker, ViewContainer, } from 'pixi.js';
29
+ import { AnimationState, AnimationStateData, AtlasAttachmentLoader, ClippingAttachment, Color, MeshAttachment, Physics, Pool, RegionAttachment, Skeleton, SkeletonBinary, SkeletonBounds, SkeletonClipping, SkeletonData, SkeletonJson, Skin, Vector2, } from '@esotericsoftware/spine-core';
30
+ import { Assets, Cache, Container, fastCopy, Graphics, Texture, Ticker, ViewContainer, } from 'pixi.js';
31
31
  const vectorAux = new Vector2();
32
32
  Skeleton.yDown = true;
33
33
  const clipper = new SkeletonClipping();
34
+ /** A bounds provider that provides a fixed size given by the user. */
35
+ export class AABBRectangleBoundsProvider {
36
+ constructor(x, y, width, height) {
37
+ this.x = x;
38
+ this.y = y;
39
+ this.width = width;
40
+ this.height = height;
41
+ }
42
+ calculateBounds() {
43
+ return { x: this.x, y: this.y, width: this.width, height: this.height };
44
+ }
45
+ }
46
+ /** A bounds provider that calculates the bounding box from the setup pose. */
47
+ export class SetupPoseBoundsProvider {
48
+ /**
49
+ * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
50
+ */
51
+ constructor(clipping = false) {
52
+ this.clipping = clipping;
53
+ }
54
+ calculateBounds(gameObject) {
55
+ if (!gameObject.skeleton)
56
+ return { x: 0, y: 0, width: 0, height: 0 };
57
+ // Make a copy of animation state and skeleton as this might be called while
58
+ // the skeleton in the GameObject has already been heavily modified. We can not
59
+ // reconstruct that state.
60
+ const skeleton = new Skeleton(gameObject.skeleton.data);
61
+ skeleton.setToSetupPose();
62
+ skeleton.updateWorldTransform(Physics.update);
63
+ const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined);
64
+ return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds;
65
+ }
66
+ }
67
+ /** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */
68
+ export class SkinsAndAnimationBoundsProvider {
69
+ /**
70
+ * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.
71
+ * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.
72
+ * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.
73
+ * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
74
+ */
75
+ constructor(animation, skins = [], timeStep = 0.05, clipping = false) {
76
+ this.animation = animation;
77
+ this.skins = skins;
78
+ this.timeStep = timeStep;
79
+ this.clipping = clipping;
80
+ }
81
+ calculateBounds(gameObject) {
82
+ if (!gameObject.skeleton || !gameObject.state)
83
+ return { x: 0, y: 0, width: 0, height: 0 };
84
+ // Make a copy of animation state and skeleton as this might be called while
85
+ // the skeleton in the GameObject has already been heavily modified. We can not
86
+ // reconstruct that state.
87
+ const animationState = new AnimationState(gameObject.state.data);
88
+ const skeleton = new Skeleton(gameObject.skeleton.data);
89
+ const clipper = this.clipping ? new SkeletonClipping() : undefined;
90
+ const data = skeleton.data;
91
+ if (this.skins.length > 0) {
92
+ const customSkin = new Skin('custom-skin');
93
+ for (const skinName of this.skins) {
94
+ const skin = data.findSkin(skinName);
95
+ if (skin == null)
96
+ continue;
97
+ customSkin.addSkin(skin);
98
+ }
99
+ skeleton.setSkin(customSkin);
100
+ }
101
+ skeleton.setToSetupPose();
102
+ const animation = this.animation != null ? data.findAnimation(this.animation) : null;
103
+ if (animation == null) {
104
+ skeleton.updateWorldTransform(Physics.update);
105
+ const bounds = skeleton.getBoundsRect(clipper);
106
+ return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds;
107
+ }
108
+ else {
109
+ let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
110
+ animationState.clearTracks();
111
+ animationState.setAnimationWith(0, animation, false);
112
+ const steps = Math.max(animation.duration / this.timeStep, 1.0);
113
+ for (let i = 0; i < steps; i++) {
114
+ const delta = i > 0 ? this.timeStep : 0;
115
+ animationState.update(delta);
116
+ animationState.apply(skeleton);
117
+ skeleton.update(delta);
118
+ skeleton.updateWorldTransform(Physics.update);
119
+ const bounds = skeleton.getBoundsRect(clipper);
120
+ minX = Math.min(minX, bounds.x);
121
+ minY = Math.min(minY, bounds.y);
122
+ maxX = Math.max(maxX, bounds.x + bounds.width);
123
+ maxY = Math.max(maxY, bounds.y + bounds.height);
124
+ }
125
+ const bounds = {
126
+ x: minX,
127
+ y: minY,
128
+ width: maxX - minX,
129
+ height: maxY - minY,
130
+ };
131
+ return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds;
132
+ }
133
+ }
134
+ }
34
135
  const maskPool = new Pool(() => new Graphics());
35
136
  /**
36
137
  * The class to instantiate a {@link Spine} game object in Pixi.
@@ -69,14 +170,25 @@ export class Spine extends ViewContainer {
69
170
  }
70
171
  /** When `true`, the Spine AnimationState and the Skeleton will be automatically updated using the {@link Ticker.shared} instance. */
71
172
  set autoUpdate(value) {
72
- if (value) {
173
+ if (value && !this._autoUpdate) {
73
174
  Ticker.shared.add(this.internalUpdate, this);
74
175
  }
75
- else {
176
+ else if (!value && this._autoUpdate) {
76
177
  Ticker.shared.remove(this.internalUpdate, this);
77
178
  }
78
179
  this._autoUpdate = value;
79
180
  }
181
+ /** The bounds provider to use. If undefined the bounds will be dynamic, calculated when requested and based on the current frame. */
182
+ get boundsProvider() {
183
+ return this._boundsProvider;
184
+ }
185
+ set boundsProvider(value) {
186
+ this._boundsProvider = value;
187
+ if (value) {
188
+ this._boundsDirty = false;
189
+ }
190
+ this.updateBounds();
191
+ }
80
192
  constructor(options) {
81
193
  var _a;
82
194
  if (options instanceof SkeletonData) {
@@ -84,7 +196,7 @@ export class Spine extends ViewContainer {
84
196
  skeletonData: options,
85
197
  };
86
198
  }
87
- super(options);
199
+ super({});
88
200
  // Pixi properties
89
201
  this.batched = true;
90
202
  this.buildId = 0;
@@ -105,8 +217,9 @@ export class Spine extends ViewContainer {
105
217
  this._lastAttachments = [];
106
218
  this._stateChanged = true;
107
219
  this.attachmentCacheData = [];
108
- this._autoUpdate = true;
220
+ this._autoUpdate = false;
109
221
  this.hasNeverUpdated = true;
222
+ this.allowChildren = true;
110
223
  const skeletonData = options instanceof SkeletonData ? options : options.skeletonData;
111
224
  this.skeleton = new Skeleton(skeletonData);
112
225
  this.state = new AnimationState(new AnimationStateData(skeletonData));
@@ -117,6 +230,7 @@ export class Spine extends ViewContainer {
117
230
  for (let i = 0; i < slots.length; i++) {
118
231
  this.attachmentCacheData[i] = Object.create(null);
119
232
  }
233
+ this._boundsProvider = options.boundsProvider;
120
234
  }
121
235
  /** If {@link Spine.autoUpdate} is `false`, this method allows to update the AnimationState and the Skeleton with the given delta. */
122
236
  update(dt) {
@@ -196,7 +310,6 @@ export class Spine extends ViewContainer {
196
310
  this.afterUpdateWorldTransforms(this);
197
311
  this.updateSlotObjects();
198
312
  this._stateChanged = true;
199
- this._boundsDirty = true;
200
313
  this.onViewUpdate();
201
314
  }
202
315
  /**
@@ -240,15 +353,13 @@ export class Spine extends ViewContainer {
240
353
  if (attachment && attachment instanceof ClippingAttachment) {
241
354
  const clip = ((_a = this.clippingSlotToPixiMasks)[_b = slot.data.name] || (_a[_b] = { slot, vertices: new Array() }));
242
355
  clip.maskComputed = false;
243
- this.currentClippingSlot = this.clippingSlotToPixiMasks[slot.data.name];
356
+ this.currentClippingSlot = clip;
244
357
  return;
245
358
  }
246
359
  // assign the currentClippingSlot mask to the slot object
247
360
  const currentClippingSlot = this.currentClippingSlot;
248
361
  const slotObject = this._slotsObject[slot.data.name];
249
362
  if (currentClippingSlot && slotObject) {
250
- const slotClipping = currentClippingSlot.slot;
251
- const clippingAttachment = slotClipping.attachment;
252
363
  // create the pixi mask, only the first time and if the clipped slot is the first one clipped by this currentClippingSlot
253
364
  let mask = currentClippingSlot.mask;
254
365
  if (!mask) {
@@ -258,6 +369,8 @@ export class Spine extends ViewContainer {
258
369
  }
259
370
  // compute the pixi mask polygon, if the clipped slot is the first one clipped by this currentClippingSlot
260
371
  if (!currentClippingSlot.maskComputed) {
372
+ const slotClipping = currentClippingSlot.slot;
373
+ const clippingAttachment = slotClipping.attachment;
261
374
  currentClippingSlot.maskComputed = true;
262
375
  const worldVerticesLength = clippingAttachment.worldVerticesLength;
263
376
  const vertices = currentClippingSlot.vertices;
@@ -285,6 +398,7 @@ export class Spine extends ViewContainer {
285
398
  clippingSlotToPixiMask.mask = undefined;
286
399
  }
287
400
  }
401
+ this.currentClippingSlot = undefined;
288
402
  }
289
403
  }
290
404
  transformAttachments() {
@@ -313,18 +427,28 @@ export class Spine extends ViewContainer {
313
427
  const skeletonColor = skeleton.color;
314
428
  const slotColor = slot.color;
315
429
  const attachmentColor = attachment.color;
316
- cacheData.color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, skeletonColor.a * slotColor.a * attachmentColor.a);
317
- if (slot.darkColor) {
318
- cacheData.darkColor.setFromColor(slot.darkColor);
319
- }
320
- cacheData.skipRender = cacheData.clipped = false;
321
- const texture = ((_a = attachment.region) === null || _a === void 0 ? void 0 : _a.texture.texture) || Texture.EMPTY;
322
- if (cacheData.texture !== texture) {
323
- cacheData.texture = texture;
324
- this.spineTexturesDirty = true;
430
+ const alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
431
+ cacheData.color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
432
+ if (this.alpha === 0 || alpha === 0) {
433
+ if (!cacheData.skipRender)
434
+ this.spineAttachmentsDirty = true;
435
+ cacheData.skipRender = true;
325
436
  }
326
- if (clipper.isClipping()) {
327
- this.updateClippingData(cacheData);
437
+ else {
438
+ if (cacheData.skipRender)
439
+ this.spineAttachmentsDirty = true;
440
+ cacheData.skipRender = cacheData.clipped = false;
441
+ if (slot.darkColor) {
442
+ cacheData.darkColor.setFromColor(slot.darkColor);
443
+ }
444
+ const texture = ((_a = attachment.region) === null || _a === void 0 ? void 0 : _a.texture.texture) || Texture.EMPTY;
445
+ if (cacheData.texture !== texture) {
446
+ cacheData.texture = texture;
447
+ this.spineTexturesDirty = true;
448
+ }
449
+ if (clipper.isClipping()) {
450
+ this.updateClippingData(cacheData);
451
+ }
328
452
  }
329
453
  }
330
454
  else if (attachment instanceof ClippingAttachment) {
@@ -396,13 +520,22 @@ export class Spine extends ViewContainer {
396
520
  }
397
521
  updateSlotObject(slotAttachment) {
398
522
  const { slot, container } = slotAttachment;
399
- container.visible = this.skeleton.drawOrder.includes(slot);
523
+ const followAttachmentValue = slotAttachment.followAttachmentTimeline ? Boolean(slot.attachment) : true;
524
+ container.visible = this.skeleton.drawOrder.includes(slot) && followAttachmentValue;
400
525
  if (container.visible) {
401
- const bone = slot.bone;
526
+ let bone = slot.bone;
402
527
  container.position.set(bone.worldX, bone.worldY);
403
- container.scale.x = bone.getWorldScaleX();
404
- container.scale.y = bone.getWorldScaleY();
405
- container.rotation = bone.getWorldRotationX() * DEG_TO_RAD;
528
+ container.angle = bone.getWorldRotationX();
529
+ let cumulativeScaleX = 1;
530
+ let cumulativeScaleY = 1;
531
+ while (bone) {
532
+ cumulativeScaleX *= bone.scaleX;
533
+ cumulativeScaleY *= bone.scaleY;
534
+ bone = bone.parent;
535
+ }
536
+ if (cumulativeScaleX < 0)
537
+ container.angle -= 180;
538
+ container.scale.set(slot.bone.getWorldScaleX() * Math.sign(cumulativeScaleX), slot.bone.getWorldScaleY() * Math.sign(cumulativeScaleY));
406
539
  container.alpha = this.skeleton.color.a * slot.color.a;
407
540
  }
408
541
  }
@@ -449,7 +582,9 @@ export class Spine extends ViewContainer {
449
582
  var _a;
450
583
  // increment from the 12th bit!
451
584
  this._didViewChangeTick++;
452
- this._boundsDirty = true;
585
+ if (!this._boundsProvider) {
586
+ this._boundsDirty = true;
587
+ }
453
588
  if (this.didViewUpdate)
454
589
  return;
455
590
  this.didViewUpdate = true;
@@ -465,8 +600,10 @@ export class Spine extends ViewContainer {
465
600
  *
466
601
  * @param container - The container to attach to the slot
467
602
  * @param slotRef - The slot id or slot to attach to
603
+ * @param options - Optional settings for the attachment.
604
+ * @param options.followAttachmentTimeline - If true, the attachment will follow the slot's attachment timeline.
468
605
  */
469
- addSlotObject(slot, container) {
606
+ addSlotObject(slot, container, options) {
470
607
  var _a;
471
608
  slot = this.getSlotFromRef(slot);
472
609
  // need to check in on the container too...
@@ -477,9 +614,12 @@ export class Spine extends ViewContainer {
477
614
  }
478
615
  this.removeSlotObject(slot);
479
616
  container.includeInBuild = false;
480
- // TODO only add once??
481
617
  this.addChild(container);
482
- const slotObject = { container, slot };
618
+ const slotObject = {
619
+ container,
620
+ slot,
621
+ followAttachmentTimeline: (options === null || options === void 0 ? void 0 : options.followAttachmentTimeline) || false,
622
+ };
483
623
  this._slotsObject[slot.data.name] = slotObject;
484
624
  this.updateSlotObject(slotObject);
485
625
  }
@@ -511,6 +651,16 @@ export class Spine extends ViewContainer {
511
651
  containerToRemove.includeInBuild = true;
512
652
  }
513
653
  }
654
+ /**
655
+ * Removes all PixiJS containers attached to any slot.
656
+ */
657
+ removeSlotObjects() {
658
+ Object.entries(this._slotsObject).forEach(([slotName, slotObject]) => {
659
+ if (slotObject)
660
+ slotObject.container.removeFromParent();
661
+ delete this._slotsObject[slotName];
662
+ });
663
+ }
514
664
  /**
515
665
  * Returns a container attached to a slot, or undefined if no container is attached.
516
666
  *
@@ -527,7 +677,16 @@ export class Spine extends ViewContainer {
527
677
  this.skeletonBounds || (this.skeletonBounds = new SkeletonBounds());
528
678
  const skeletonBounds = this.skeletonBounds;
529
679
  skeletonBounds.update(this.skeleton, true);
530
- if (skeletonBounds.minX === Infinity) {
680
+ if (this._boundsProvider) {
681
+ const boundsSpine = this._boundsProvider.calculateBounds(this);
682
+ const bounds = this._bounds;
683
+ bounds.clear();
684
+ bounds.x = boundsSpine.x;
685
+ bounds.y = boundsSpine.y;
686
+ bounds.width = boundsSpine.width;
687
+ bounds.height = boundsSpine.height;
688
+ }
689
+ else if (skeletonBounds.minX === Infinity) {
531
690
  if (this.hasNeverUpdated) {
532
691
  this._updateAndApplyState(0);
533
692
  this._boundsDirty = false;
@@ -596,8 +755,8 @@ export class Spine extends ViewContainer {
596
755
  * Use this method to instantiate a Spine game object.
597
756
  * Before instantiating a Spine game object, the skeleton (`.skel` or `.json`) and the atlas text files must be loaded into the Assets. For example:
598
757
  * ```
599
- * PIXI.Assets.add("sackData", "./assets/sack-pro.skel");
600
- * PIXI.Assets.add("sackAtlas", "./assets/sack-pma.atlas");
758
+ * PIXI.Assets.add("sackData", "/assets/sack-pro.skel");
759
+ * PIXI.Assets.add("sackAtlas", "/assets/sack-pma.atlas");
601
760
  * await PIXI.Assets.load(["sackData", "sackAtlas"]);
602
761
  * ```
603
762
  * Once a Spine game object is created, its skeleton data is cached into {@link Cache} using the key:
@@ -606,10 +765,15 @@ export class Spine extends ViewContainer {
606
765
  * @param options - Options to configure the Spine game object. See {@link SpineFromOptions}
607
766
  * @returns {Spine} The Spine game object instantiated
608
767
  */
609
- static from({ skeleton, atlas, scale = 1, darkTint, autoUpdate = true }) {
768
+ static from({ skeleton, atlas, scale = 1, darkTint, autoUpdate = true, boundsProvider }) {
610
769
  const cacheKey = `${skeleton}-${atlas}-${scale}`;
611
770
  if (Cache.has(cacheKey)) {
612
- return new Spine(Cache.get(cacheKey));
771
+ return new Spine({
772
+ skeletonData: Cache.get(cacheKey),
773
+ darkTint,
774
+ autoUpdate,
775
+ boundsProvider,
776
+ });
613
777
  }
614
778
  const skeletonAsset = Assets.get(skeleton);
615
779
  const atlasAsset = Assets.get(atlas);
@@ -622,6 +786,7 @@ export class Spine extends ViewContainer {
622
786
  skeletonData,
623
787
  darkTint,
624
788
  autoUpdate,
789
+ boundsProvider,
625
790
  });
626
791
  }
627
792
  }
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,8 +23,8 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
29
  import { Container, Graphics } from 'pixi.js';
30
30
  import { Spine } from './Spine.js';
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,8 +23,8 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
29
  import { Container, Graphics, Text } from 'pixi.js';
30
30
  import { ClippingAttachment, MeshAttachment, PathAttachment, RegionAttachment, SkeletonBounds } from '@esotericsoftware/spine-core';
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,11 +23,11 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
- import { ExtensionType, InstructionSet, type Renderer, type RenderPipe } from 'pixi.js';
30
- import { Spine } from './Spine.js';
29
+ import { ExtensionType, type InstructionSet, type Renderer, type RenderPipe } from 'pixi.js';
30
+ import type { Spine } from './Spine.js';
31
31
  export declare class SpinePipe implements RenderPipe<Spine> {
32
32
  /** @ignore */
33
33
  static extension: {
@@ -1 +1 @@
1
- {"version":3,"file":"SpinePipe.d.ts","sourceRoot":"","sources":["../../../src/spine/lib/SpinePipe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;+EA2B+E;AAE/E,OAAO,EAEM,aAAa,EACzB,cAAc,EAGd,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAanC,qBAAa,SAAU,YAAW,UAAU,CAAC,KAAK,CAAC;IAClD,cAAc;IACd,MAAM,CAAC,SAAS;;;MAOL;IAEX,QAAQ,EAAE,QAAQ,CAAC;IAEnB,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAwE;gBAEnG,QAAQ,EAAE,QAAQ;IAI/B,kBAAkB,CAAE,KAAK,EAAE,KAAK,GAAG,OAAO;IAoC1C,aAAa,CAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc;IA+C3D,gBAAgB,CAAE,KAAK,EAAE,KAAK;IA0B9B,iBAAiB,CAAE,KAAK,EAAE,KAAK;IAK/B,OAAO;IAKP,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,aAAa;CAKrB"}
1
+ {"version":3,"file":"SpinePipe.d.ts","sourceRoot":"","sources":["../../../src/spine/lib/SpinePipe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;+EA2B+E;AAG/E,OAAO,EAEU,aAAa,EAE7B,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAYxC,qBAAa,SAAU,YAAW,UAAU,CAAC,KAAK,CAAC;IAClD,cAAc;IACd,MAAM,CAAC,SAAS;;;MAOL;IAEX,QAAQ,EAAE,QAAQ,CAAC;IAEnB,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAwE;gBAEnG,QAAQ,EAAE,QAAQ;IAI/B,kBAAkB,CAAE,KAAK,EAAE,KAAK,GAAG,OAAO;IAoC1C,aAAa,CAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc;IAqD3D,gBAAgB,CAAE,KAAK,EAAE,KAAK;IA0B9B,iBAAiB,CAAE,KAAK,EAAE,KAAK;IAK/B,OAAO;IAKP,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,aAAa;CAKrB"}
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,12 +23,12 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
- import { collectAllRenderables, extensions, ExtensionType, } from 'pixi.js';
30
- import { BatchableSpineSlot } from './BatchableSpineSlot.js';
31
29
  import { MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-core';
30
+ import { ExtensionType, extensions, } from 'pixi.js';
31
+ import { BatchableSpineSlot } from './BatchableSpineSlot.js';
32
32
  const spineBlendModeMap = {
33
33
  0: 'normal',
34
34
  1: 'add',
@@ -83,19 +83,24 @@ export class SpinePipe {
83
83
  const slot = drawOrder[i];
84
84
  const attachment = slot.getAttachment();
85
85
  const blendMode = spineBlendModeMap[slot.data.blendMode];
86
+ let skipRender = false;
86
87
  if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) {
87
88
  const cacheData = spine._getCachedData(slot, attachment);
88
89
  const batchableSpineSlot = (_a = gpuSpine.slotBatches)[_b = cacheData.id] || (_a[_b] = new BatchableSpineSlot());
89
90
  batchableSpineSlot.setData(spine, cacheData, blendMode, roundPixels);
90
- if (!cacheData.skipRender) {
91
+ skipRender = cacheData.skipRender;
92
+ if (!skipRender) {
91
93
  batcher.addToBatch(batchableSpineSlot, instructionSet);
92
94
  }
93
95
  }
94
96
  const containerAttachment = spine._slotsObject[slot.data.name];
95
97
  if (containerAttachment) {
96
98
  const container = containerAttachment.container;
97
- container.includeInBuild = true;
98
- collectAllRenderables(container, instructionSet, this.renderer);
99
+ if (!skipRender) {
100
+ container.includeInBuild = true;
101
+ // See https://github.com/pixijs/pixijs/blob/b4c050a791fe65e979e467c9cba2bda0c01a1c35/src/scene/container/utils/collectAllRenderables.ts#L28
102
+ container.collectRenderables(instructionSet, this.renderer, null);
103
+ }
99
104
  container.includeInBuild = false;
100
105
  }
101
106
  }
@@ -1,16 +1,16 @@
1
- /** ****************************************************************************
1
+ /******************************************************************************
2
2
  * Spine Runtimes License Agreement
3
- * Last updated July 28, 2023. Replaces all prior versions.
3
+ * Last updated April 5, 2025. Replaces all prior versions.
4
4
  *
5
- * Copyright (c) 2013-2023, Esoteric Software LLC
5
+ * Copyright (c) 2013-2025, Esoteric Software LLC
6
6
  *
7
7
  * Integration of the Spine Runtimes into software or otherwise creating
8
8
  * derivative works of the Spine Runtimes is permitted under the terms and
9
9
  * conditions of Section 2 of the Spine Editor License Agreement:
10
10
  * http://esotericsoftware.com/spine-editor-license
11
11
  *
12
- * Otherwise, it is permitted to integrate the Spine Runtimes into software or
13
- * otherwise create derivative works of the Spine Runtimes (collectively,
12
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
13
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
14
14
  * "Products"), provided that each user of the Products must obtain their own
15
15
  * Spine Editor license and redistribution of the Products in any form must
16
16
  * include this license and copyright notice.
@@ -23,8 +23,8 @@
23
23
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24
24
  * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25
25
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
27
- * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  *****************************************************************************/
29
29
  import { Texture as PixiTexture } from 'pixi.js';
30
30
  import { BlendMode, Texture, TextureFilter, TextureWrap } from '@esotericsoftware/spine-core';