@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.
- package/dist/app.d.ts +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +14 -3
- package/dist/spine/lib/BatchableSpineSlot.d.ts +7 -7
- package/dist/spine/lib/BatchableSpineSlot.js +7 -7
- package/dist/spine/lib/Spine.d.ts +89 -14
- package/dist/spine/lib/Spine.d.ts.map +1 -1
- package/dist/spine/lib/Spine.js +207 -42
- package/dist/spine/lib/SpineDebugRenderer.d.ts +7 -7
- package/dist/spine/lib/SpineDebugRenderer.js +7 -7
- package/dist/spine/lib/SpinePipe.d.ts +9 -9
- package/dist/spine/lib/SpinePipe.d.ts.map +1 -1
- package/dist/spine/lib/SpinePipe.js +17 -12
- package/dist/spine/lib/SpineTexture.d.ts +7 -7
- package/dist/spine/lib/SpineTexture.js +7 -7
- package/dist/spine/lib/assets/atlasLoader.d.ts +7 -7
- package/dist/spine/lib/assets/atlasLoader.d.ts.map +1 -1
- package/dist/spine/lib/assets/atlasLoader.js +16 -12
- package/dist/spine/lib/assets/skeletonLoader.d.ts +7 -7
- package/dist/spine/lib/assets/skeletonLoader.js +14 -10
- package/dist/spine/lib/darktint/DarkTintBatchGeometry.d.ts +6 -6
- package/dist/spine/lib/darktint/DarkTintBatchGeometry.js +6 -6
- package/dist/spine/lib/darktint/DarkTintBatcher.d.ts +6 -6
- package/dist/spine/lib/darktint/DarkTintBatcher.js +6 -6
- package/dist/spine/lib/darktint/DarkTintShader.d.ts +6 -6
- package/dist/spine/lib/darktint/DarkTintShader.js +6 -6
- package/dist/spine/lib/darktint/darkTintBit.d.ts +6 -6
- package/dist/spine/lib/darktint/darkTintBit.js +6 -6
- package/dist/spine/lib/index.d.ts +1 -1
- package/dist/spine/lib/index.js +1 -1
- package/dist/spine/lib/require-shim.d.ts +7 -7
- package/dist/spine/lib/require-shim.js +7 -7
- package/package.json +1 -1
package/dist/spine/lib/Spine.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/******************************************************************************
|
|
2
2
|
* Spine Runtimes License Agreement
|
|
3
|
-
* Last updated
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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,
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
|
|
327
|
-
|
|
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
|
-
|
|
523
|
+
const followAttachmentValue = slotAttachment.followAttachmentTimeline ? Boolean(slot.attachment) : true;
|
|
524
|
+
container.visible = this.skeleton.drawOrder.includes(slot) && followAttachmentValue;
|
|
400
525
|
if (container.visible) {
|
|
401
|
-
|
|
526
|
+
let bone = slot.bone;
|
|
402
527
|
container.position.set(bone.worldX, bone.worldY);
|
|
403
|
-
container.
|
|
404
|
-
|
|
405
|
-
|
|
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.
|
|
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 = {
|
|
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 (
|
|
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", "
|
|
600
|
-
* PIXI.Assets.add("sackAtlas", "
|
|
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(
|
|
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
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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;
|
|
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
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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
|
|
3
|
+
* Last updated April 5, 2025. Replaces all prior versions.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c) 2013-
|
|
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
|
|
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
|
|
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';
|