@eva/spine-base 2.1.0-beta.11 → 2.1.0-beta.12
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/README.md +16 -0
- package/dist/EVA.plugin.spineBase.js +102 -47
- package/dist/EVA.plugin.spineBase.min.js +1 -1
- package/dist/spine-base.cjs.js +109 -47
- package/dist/spine-base.cjs.prod.js +1 -1
- package/dist/spine-base.d.ts +14 -12
- package/dist/spine-base.esm.js +109 -47
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,3 +4,19 @@ More Introduction
|
|
|
4
4
|
|
|
5
5
|
- [EN](https://eva.js.org)
|
|
6
6
|
- [中文](https://eva-engine.gitee.io)
|
|
7
|
+
|
|
8
|
+
## Slot object readiness
|
|
9
|
+
|
|
10
|
+
`Spine#addSlotObject(slot, gameObject, options)` is safe to call before the
|
|
11
|
+
Spine armature, renderer container manager, or target GameObject container is
|
|
12
|
+
ready. The component keeps the latest request for each GameObject and mounts it
|
|
13
|
+
once all three dependencies are available.
|
|
14
|
+
|
|
15
|
+
- Repeating the call for one GameObject replaces its previous pending or mounted
|
|
16
|
+
slot request.
|
|
17
|
+
- `removeSlotObject(gameObject)` cancels both pending and mounted requests.
|
|
18
|
+
- Destroying the Spine component destroys pending and mounted slot GameObjects.
|
|
19
|
+
- Invalid slots are discarded with a warning after skeleton metadata becomes
|
|
20
|
+
available.
|
|
21
|
+
|
|
22
|
+
Do not force a resource reload merely to retry a slot mount.
|
|
@@ -182,6 +182,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
this.waitExecuteInfos = [];
|
|
185
|
+
this._flushPendingSlotObjects();
|
|
185
186
|
}
|
|
186
187
|
get armature() {
|
|
187
188
|
return this._armature;
|
|
@@ -212,8 +213,8 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
212
213
|
}
|
|
213
214
|
destroy() {
|
|
214
215
|
this.onDestroy();
|
|
216
|
+
this._destroySlotGameObjects();
|
|
215
217
|
if (this.armature && !this.armature.destroyed) {
|
|
216
|
-
this._destroySlotGameObjects();
|
|
217
218
|
this.armature.destroy({
|
|
218
219
|
children: true
|
|
219
220
|
});
|
|
@@ -324,24 +325,22 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
324
325
|
return this.armature.skeleton.findBone(boneName);
|
|
325
326
|
}
|
|
326
327
|
addSlotObject(slot, gameObject, options) {
|
|
327
|
-
if (
|
|
328
|
-
console.warn('Spine
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
if (!this._containerManager) {
|
|
332
|
-
console.warn('ContainerManager is not available');
|
|
328
|
+
if (this.destroied) {
|
|
329
|
+
console.warn('Spine component has been destroyed, cannot addSlotObject');
|
|
333
330
|
return;
|
|
334
331
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
this._pendingSlotObjects.push({
|
|
338
|
-
slot,
|
|
339
|
-
gameObject,
|
|
340
|
-
options
|
|
341
|
-
});
|
|
332
|
+
if (!gameObject || gameObject.destroyed) {
|
|
333
|
+
console.warn('Cannot add a destroyed or missing GameObject to a Spine slot');
|
|
342
334
|
return;
|
|
343
335
|
}
|
|
344
|
-
this.
|
|
336
|
+
this._pendingSlotObjects = this._pendingSlotObjects.filter(pending => pending.gameObject !== gameObject);
|
|
337
|
+
this._detachSlotObject(gameObject);
|
|
338
|
+
this._pendingSlotObjects.push({
|
|
339
|
+
slot,
|
|
340
|
+
gameObject,
|
|
341
|
+
options
|
|
342
|
+
});
|
|
343
|
+
this._flushPendingSlotObjects();
|
|
345
344
|
}
|
|
346
345
|
_doAddSlotObject(slot, gameObject, container, options) {
|
|
347
346
|
const wrapper = new pixi_js.Container();
|
|
@@ -353,6 +352,31 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
353
352
|
});
|
|
354
353
|
this._syncTransformTree(gameObject);
|
|
355
354
|
}
|
|
355
|
+
_isSlotAvailable(slot) {
|
|
356
|
+
var _a, _b, _c, _d;
|
|
357
|
+
if (typeof slot === 'number') {
|
|
358
|
+
if (!Number.isInteger(slot) || slot < 0) return false;
|
|
359
|
+
const slots = (_b = (_a = this.armature) === null || _a === void 0 ? void 0 : _a.skeleton) === null || _b === void 0 ? void 0 : _b.slots;
|
|
360
|
+
return !Array.isArray(slots) || slot < slots.length;
|
|
361
|
+
}
|
|
362
|
+
if (typeof slot !== 'string' || slot.length === 0) return false;
|
|
363
|
+
const findSlot = (_d = (_c = this.armature) === null || _c === void 0 ? void 0 : _c.skeleton) === null || _d === void 0 ? void 0 : _d.findSlot;
|
|
364
|
+
return typeof findSlot !== 'function' || Boolean(findSlot.call(this.armature.skeleton, slot));
|
|
365
|
+
}
|
|
366
|
+
_detachSlotObject(gameObject) {
|
|
367
|
+
const entry = this._slotGameObjects.get(gameObject);
|
|
368
|
+
if (!entry) return;
|
|
369
|
+
if (this.armature && !this.armature.destroyed) {
|
|
370
|
+
this.armature.removeSlotObject(entry.wrapper);
|
|
371
|
+
}
|
|
372
|
+
for (const child of [...entry.wrapper.children]) {
|
|
373
|
+
entry.wrapper.removeChild(child);
|
|
374
|
+
}
|
|
375
|
+
entry.wrapper.destroy({
|
|
376
|
+
children: false
|
|
377
|
+
});
|
|
378
|
+
this._slotGameObjects.delete(gameObject);
|
|
379
|
+
}
|
|
356
380
|
_syncTransformTree(gameObject) {
|
|
357
381
|
var _a;
|
|
358
382
|
if (!this._containerManager) return;
|
|
@@ -369,39 +393,39 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
369
393
|
}
|
|
370
394
|
}
|
|
371
395
|
_flushPendingSlotObjects() {
|
|
372
|
-
if (this._pendingSlotObjects.length === 0) return;
|
|
396
|
+
if (this.destroied || this._pendingSlotObjects.length === 0) return;
|
|
373
397
|
if (!this.armature || !this._containerManager) return;
|
|
374
398
|
const still = [];
|
|
375
|
-
|
|
399
|
+
const pendingSlotObjects = this._pendingSlotObjects;
|
|
400
|
+
this._pendingSlotObjects = [];
|
|
401
|
+
for (const pending of pendingSlotObjects) {
|
|
402
|
+
if (pending.gameObject.destroyed) continue;
|
|
403
|
+
if (!this._isSlotAvailable(pending.slot)) {
|
|
404
|
+
console.warn(`Spine slot "${pending.slot}" does not exist; pending slot object was discarded`);
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
376
407
|
const container = this._containerManager.getContainer(pending.gameObject.id);
|
|
377
408
|
if (container) {
|
|
378
|
-
|
|
409
|
+
try {
|
|
410
|
+
this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.warn(`Failed to add GameObject to Spine slot "${pending.slot}"`, error);
|
|
413
|
+
}
|
|
379
414
|
} else {
|
|
380
415
|
still.push(pending);
|
|
381
416
|
}
|
|
382
417
|
}
|
|
383
|
-
this._pendingSlotObjects
|
|
418
|
+
this._pendingSlotObjects.push(...still);
|
|
384
419
|
}
|
|
385
420
|
removeSlotObject(gameObject) {
|
|
386
421
|
this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
|
|
387
|
-
|
|
388
|
-
if (entry && this.armature) {
|
|
389
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
390
|
-
entry.wrapper.destroy({
|
|
391
|
-
children: false
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
this._slotGameObjects.delete(gameObject);
|
|
422
|
+
this._detachSlotObject(gameObject);
|
|
395
423
|
}
|
|
396
424
|
_destroySlotGameObjects() {
|
|
397
|
-
|
|
425
|
+
const gameObjects = new Set([...this._slotGameObjects.keys(), ...this._pendingSlotObjects.map(pending => pending.gameObject)]);
|
|
426
|
+
for (const gameObject of gameObjects) {
|
|
427
|
+
this._detachSlotObject(gameObject);
|
|
398
428
|
if (!gameObject.destroyed) {
|
|
399
|
-
if (this.armature) {
|
|
400
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
401
|
-
}
|
|
402
|
-
entry.wrapper.destroy({
|
|
403
|
-
children: false
|
|
404
|
-
});
|
|
405
429
|
gameObject.destroy();
|
|
406
430
|
}
|
|
407
431
|
}
|
|
@@ -453,17 +477,25 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
453
477
|
return data.spineData;
|
|
454
478
|
});
|
|
455
479
|
}
|
|
456
|
-
function releaseSpineData(res, _imageSrc) {
|
|
480
|
+
function releaseSpineData(res, _imageSrc, destroyResource = true) {
|
|
457
481
|
const resourceName = res.name;
|
|
458
482
|
const data = dataMap[resourceName];
|
|
459
483
|
if (!data) {
|
|
460
484
|
return;
|
|
461
485
|
}
|
|
462
486
|
data.ref--;
|
|
487
|
+
if (data.ref > 0) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (dataMap[resourceName] === data) {
|
|
491
|
+
delete dataMap[resourceName];
|
|
492
|
+
}
|
|
493
|
+
if (!destroyResource) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
463
496
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
464
|
-
if (data.ref <= 0) {
|
|
497
|
+
if (data.ref <= 0 && !dataMap[resourceName]) {
|
|
465
498
|
eva_js.resource.destroy(resourceName);
|
|
466
|
-
delete dataMap[resourceName];
|
|
467
499
|
}
|
|
468
500
|
}), 100);
|
|
469
501
|
}
|
|
@@ -520,6 +552,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
520
552
|
const armature = this.armatures[key];
|
|
521
553
|
const component = this._spineComponents[key];
|
|
522
554
|
if (!armature || armature.destroyed || (component === null || component === void 0 ? void 0 : component.destroied)) {
|
|
555
|
+
this.releaseComponentResource(component);
|
|
523
556
|
delete this.armatures[key];
|
|
524
557
|
delete this._spineComponents[key];
|
|
525
558
|
continue;
|
|
@@ -529,6 +562,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
529
562
|
for (let key in this._spineComponents) {
|
|
530
563
|
const component = this._spineComponents[key];
|
|
531
564
|
if (!component || component.destroied) {
|
|
565
|
+
this.releaseComponentResource(component);
|
|
532
566
|
delete this._spineComponents[key];
|
|
533
567
|
continue;
|
|
534
568
|
}
|
|
@@ -639,7 +673,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
639
673
|
this.add(changed);
|
|
640
674
|
}
|
|
641
675
|
remove(changed) {
|
|
642
|
-
var _a, _b
|
|
676
|
+
var _a, _b;
|
|
643
677
|
return __awaiter(this, void 0, void 0, function* () {
|
|
644
678
|
const gameObjectId = changed.gameObject.id;
|
|
645
679
|
this.increaseAsyncId(gameObjectId);
|
|
@@ -661,19 +695,40 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
|
|
|
661
695
|
children: true
|
|
662
696
|
});
|
|
663
697
|
}
|
|
664
|
-
if (!component.keepResource && component.lastResource) {
|
|
665
|
-
try {
|
|
666
|
-
const res = yield eva_js.resource.getResource(component.lastResource);
|
|
667
|
-
const imageSrc = ((_d = (_c = res.data) === null || _c === void 0 ? void 0 : _c.image) === null || _d === void 0 ? void 0 : _d.src) || ((_f = (_e = res.data) === null || _e === void 0 ? void 0 : _e.image) === null || _f === void 0 ? void 0 : _f.label);
|
|
668
|
-
releaseSpineData(res, imageSrc);
|
|
669
|
-
} catch (error) {
|
|
670
|
-
console.warn('Failed to release Spine resource', component.lastResource, error);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
698
|
}
|
|
699
|
+
this.releaseComponentResource(component);
|
|
674
700
|
if (changed.type === eva_js.OBSERVER_TYPE.CHANGE) ;
|
|
675
701
|
});
|
|
676
702
|
}
|
|
703
|
+
onDestroy() {
|
|
704
|
+
for (const key of Object.keys(this._spineComponents)) {
|
|
705
|
+
const component = this._spineComponents[+key];
|
|
706
|
+
const armature = this.armatures[+key];
|
|
707
|
+
component === null || component === void 0 ? void 0 : component._destroySlotGameObjects();
|
|
708
|
+
if (armature && !armature.destroyed) {
|
|
709
|
+
armature.destroy({
|
|
710
|
+
children: true
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
if (component) {
|
|
714
|
+
component.armature = null;
|
|
715
|
+
}
|
|
716
|
+
this.releaseComponentResource(component);
|
|
717
|
+
}
|
|
718
|
+
this.armatures = {};
|
|
719
|
+
this._spineComponents = {};
|
|
720
|
+
this.asyncIdMap = {};
|
|
721
|
+
}
|
|
722
|
+
releaseComponentResource(component) {
|
|
723
|
+
const resourceName = component === null || component === void 0 ? void 0 : component.lastResource;
|
|
724
|
+
if (!component || !resourceName) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
component.lastResource = '';
|
|
728
|
+
releaseSpineData({
|
|
729
|
+
name: resourceName
|
|
730
|
+
}, '', !component.keepResource);
|
|
731
|
+
}
|
|
677
732
|
};
|
|
678
733
|
SpineSystem.systemName = 'SpineSystem';
|
|
679
734
|
SpineSystem = __decorate([eva_js.decorators.componentObserver({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function _extends(){return _extends=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var i in n)({}).hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e},_extends.apply(null,arguments)}globalThis.EVA=globalThis.EVA||{},globalThis.EVA.plugin=globalThis.EVA.plugin||{};var _EVA_IIFE_spineBase=function(e,t,n,i){"use strict";function r(e,t,n,i){var r,s=arguments.length,o=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(s<3?r(o):s>3?r(t,n,o):r(t,n))||o);return s>3&&o&&Object.defineProperty(t,n,o),o}function s(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function o(e,t,n,i){return new(n||(n=Promise))(function(r,s){function o(e){try{c(i.next(e))}catch(e){s(e)}}function a(e){try{c(i.throw(e))}catch(e){s(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(o,a)}c((i=i.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError,"function"==typeof SuppressedError&&SuppressedError;class a extends Error{constructor(){super("Symbol keys are not supported yet!"),Object.setPrototypeOf(this,new.target.prototype)}}const c="IDE_PROPERTY_METADATA";function l(e,t,n,i){let r=Reflect.getMetadata("design:type",e,t),s=r===Array;const o=function(e){return e===String?"string":e===Number?"number":e===Boolean?"boolean":"unknown"}(r);if("unknown"!==o&&(r=o),i){const e=i();Array.isArray(e)?(s=!0,r=e[0]):r=e}const a=Reflect.getMetadata(c,e.constructor)||{},l=_extends(_extends(_extends({},a[t]||{}),{type:r,isArray:s}),n);a[t]=l,Reflect.defineMetadata(c,a,e.constructor);!function(e,t,n){const i=e.constructor,r=i.IDEProps||{};r[t]=_extends(_extends({key:t},r[t]),n),i.IDEProps=r}(e,t,function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(i=Object.getOwnPropertySymbols(e);r<i.length;r++)t.indexOf(i[r])<0&&Object.prototype.propertyIsEnumerable.call(e,i[r])&&(n[i[r]]=e[i[r]])}return n}(l,["isArray"]))}function d(e){return t={type:e},(e,i)=>{if("symbol"==typeof i)throw new a;const{options:r,returnTypeFunc:s}=function(e,t){return"function"==typeof e?{returnTypeFunc:e,options:t||{}}:{options:e||{}}}(t,n);l(e,i,r,s)};var t,n}var u;!function(e){e[e.Edit=2]="Edit",e[e.Game=4]="Game",e[e.All=6]="All"}(u||(u={}));class m extends t.Component{constructor(e){super(e),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this.timeScale=1,this.skin="",this._slotGameObjects=new Map,this._pendingSlotObjects=[],this.waitExecuteInfos=[],this.listenerBound=!1,this.paused=!1,this.init(e)}set armature(e){if(this._armature=e,e){this.applyTimeScale(),this.skin&&this.setSkin(this.skin),this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:n,track:i}=e;this.play(t,n,i)}else this.stop(e.track);this.waitExecuteInfos=[]}}get armature(){return this._armature}init(e){e&&_extends(this,e),this.listenerBound||(this.listenerBound=!0,this.on("start",e=>{var t;null===(t=this.onStart)||void 0===t||t.call(this,e)}),this.on("complete",e=>{var t;null===(t=this.onComplete)||void 0===t||t.call(this,e)}),this.on("event",(e,t)=>{var n;null===(n=this.onEvent)||void 0===n||n.call(this,e,t)}))}onDestroy(){this.destroied=!0}load(){return this.armature}destroy(){this.onDestroy(),this.armature&&!this.armature.destroyed&&(this._destroySlotGameObjects(),this.armature.destroy({children:!0})),this.armature=null}pause(){this.paused=!0,this.applyTimeScale()}resume(){this.paused=!1,this.applyTimeScale()}setSkin(e){var t,n,i,r,s;if(this.skin=e,null===(t=this.armature)||void 0===t?void 0:t.skeleton){if(this.armature.skeleton.setSkinByName)this.armature.skeleton.setSkinByName(e);else if(this.armature.skeleton.setSkin){const t=(null===(i=null===(n=this.armature.skeleton.data)||void 0===n?void 0:n.findSkin)||void 0===i?void 0:i.call(n,e))||e;this.armature.skeleton.setSkin(t)}null===(s=(r=this.armature.skeleton).setSlotsToSetupPose)||void 0===s||s.call(r)}}play(e,t,n){try{const i=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===n&&(n=0),this.applyTimeScale(),this.armature.state.setAnimation(n,this.animationName,i)):this.waitExecuteInfos.push({playType:!0,name:e,loop:i,track:n})}catch(e){console.log(e)}}stop(e){this.armature?(void 0===e&&(e=0),this.armature.state.setEmptyAnimation(e,0)):this.waitExecuteInfos.push({playType:!1,track:e})}applyTimeScale(){var e;(null===(e=this.armature)||void 0===e?void 0:e.state)&&(this.armature.state.timeScale=this.paused?0:this.timeScale)}addAnimation(e,t,n,i){try{this.armature&&(void 0===i&&(i=0),this.armature.state.addAnimation(i,e,n,t))}catch(e){console.log(e)}}setMix(e,t,n){this.armature&&this.armature.state.data.setMix(e,t,n)}getAnim(e=0){try{if(this.armature)return this.armature.state.tracks[e].animation.name}catch(e){console.log(e)}}setDefaultMix(e){this.armature&&(this.armature.state.data.defaultMix=e)}setAttachment(e,t){this.armature&&this.armature.skeleton.setAttachment(e,t)}getBone(e){if(this.armature)return this.armature.skeleton.findBone(e)}addSlotObject(e,t,n){if(!this.armature)return void console.warn("Spine armature is not ready, cannot addSlotObject");if(!this._containerManager)return void console.warn("ContainerManager is not available");const i=this._containerManager.getContainer(t.id);i?this._doAddSlotObject(e,t,i,n):this._pendingSlotObjects.push({slot:e,gameObject:t,options:n})}_doAddSlotObject(e,t,n,r){const s=new i.Container;s.addChild(n),this.armature.addSlotObject(e,s,r),this._slotGameObjects.set(t,{slot:e,wrapper:s}),this._syncTransformTree(t)}_syncTransformTree(e){var t;if(this._containerManager&&(this._containerManager.updateTransform({name:e.id,transform:e.transform}),null===(t=e.transform)||void 0===t?void 0:t.children))for(const t of e.transform.children)t.gameObject&&this._syncTransformTree(t.gameObject)}_flushPendingSlotObjects(){if(0===this._pendingSlotObjects.length)return;if(!this.armature||!this._containerManager)return;const e=[];for(const t of this._pendingSlotObjects){const n=this._containerManager.getContainer(t.gameObject.id);n?this._doAddSlotObject(t.slot,t.gameObject,n,t.options):e.push(t)}this._pendingSlotObjects=e}removeSlotObject(e){this._pendingSlotObjects=this._pendingSlotObjects.filter(t=>t.gameObject!==e);const t=this._slotGameObjects.get(e);t&&this.armature&&(this.armature.removeSlotObject(t.wrapper),t.wrapper.destroy({children:!1})),this._slotGameObjects.delete(e)}_destroySlotGameObjects(){for(const[e,t]of this._slotGameObjects)e.destroyed||(this.armature&&this.armature.removeSlotObject(t.wrapper),t.wrapper.destroy({children:!1}),e.destroy());this._slotGameObjects.clear(),this._pendingSlotObjects=[]}}m.componentName="Spine",r([d("string"),s("design:type",String)],m.prototype,"resource",void 0),r([d("number"),s("design:type",Number)],m.prototype,"scale",void 0),r([d("string"),s("design:type",String)],m.prototype,"animationName",void 0),r([d("boolean"),s("design:type",Boolean)],m.prototype,"autoPlay",void 0),r([d("boolean"),s("design:type",Boolean)],m.prototype,"keepResource",void 0),r([d("number"),s("design:type",Number)],m.prototype,"timeScale",void 0),r([d("string"),s("design:type",String)],m.prototype,"skin",void 0);let p={};function h(e,t,n){return o(this,void 0,void 0,function*(){let i=p[e.name];if(!i)if(e.complete)i=function(e,t,n,i){const r=t.ske,s=t.atlas,o=new i.AtlasAttachmentLoader(s),a=r instanceof Uint8Array?new i.SkeletonBinary(o):new i.SkeletonJson(o);a.scale=n||1;const c={spineData:a.readSkeletonData(r),ref:0,imageSrc:(l=t.image,l?"string"==typeof l?l:l.label||(null===(d=l.source)||void 0===d?void 0:d.label)||(null===(m=null===(u=l.source)||void 0===u?void 0:u.resource)||void 0===m?void 0:m.src)||(null===(h=l.source)||void 0===h?void 0:h._sourceOrigin)||l.src||(null===(y=l.baseTexture)||void 0===y?void 0:y.cacheId)||"":"")};var l,d,u,m,h,y;return p[e]=c,c}(e.name,e.data,t,n);else if(!i)return;return i.ref++,i.spineData})}let y=class extends n.Renderer{constructor(){super(...arguments),this.armatures={},this._spineComponents={}}init({pixiSpine:e}){this.renderSystem=this.game.getSystem(n.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=e,this.game.canvas.addEventListener("webglcontextrestored",()=>{const e=this.game.gameObjects;let n=[];for(let i in this.armatures){const r=+i;for(let i=0;i<e.length;++i){let s=e[i];if(s.id===r){let e=s.getComponent(m);e&&(this.remove({type:t.OBSERVER_TYPE.REMOVE,gameObject:s,component:e,componentName:m.componentName}),n.push({type:t.OBSERVER_TYPE.ADD,gameObject:s,component:e,componentName:m.componentName}));break}}}setTimeout(()=>{n.forEach(e=>{this.add(e)})},1e3)},!1)}update(e){super.update();for(let t in this.armatures){const n=this.armatures[t],i=this._spineComponents[t];!n||n.destroyed||(null==i?void 0:i.destroied)?(delete this.armatures[t],delete this._spineComponents[t]):n.update(.001*e.deltaTime)}for(let e in this._spineComponents){const t=this._spineComponents[e];t&&!t.destroied?t._flushPendingSlotObjects():delete this._spineComponents[e]}}componentChanged(e){return o(this,void 0,void 0,function*(){if("Spine"===e.componentName)if(e.type===t.OBSERVER_TYPE.ADD)this.add(e);else if(e.type===t.OBSERVER_TYPE.CHANGE){if("resource"===e.prop.prop[0])this.change(e)}else e.type===t.OBSERVER_TYPE.REMOVE&&this.remove(e)})}add(e,n){var i,r,s;return o(this,void 0,void 0,function*(){const o=e.component;clearTimeout(o.addHandler);const a=e.gameObject.id,c=this.increaseAsyncId(a),l=yield t.resource.getResource(o.resource);if(!this.validateAsyncId(a,c)||o.destroied||e.gameObject.destroyed)return;const d=yield h(l,o.scale,this.pixiSpine);if(!this.validateAsyncId(a,c)||o.destroied||e.gameObject.destroyed)return;if(!d)return void(o.addHandler=setTimeout(()=>{o.destroied||e.gameObject.destroyed||(void 0===n&&(n=20),--n>0?this.add(e,n):console.log("retry exceed max times",o.resource))},1e3));this.remove(e);const u=null===(r=null===(i=this.renderSystem)||void 0===i?void 0:i.containerManager)||void 0===r?void 0:r.getContainer(e.gameObject.id);if(!u||o.destroied||e.gameObject.destroyed)return;o.lastResource=o.resource;const m=new this.pixiSpine.Spine({skeletonData:d,autoUpdate:!1});if(this.armatures[e.gameObject.id]=m,this._spineComponents[e.gameObject.id]=o,e.gameObject&&e.gameObject.transform){const t=e.gameObject.transform;m.x=t.size.width*t.origin.x,m.y=t.size.height*t.origin.y}u.addChildAt(m,0),m.update(),o._containerManager=null===(s=this.renderSystem)||void 0===s?void 0:s.containerManager,o.armature=m,o.emit("loaded",{resource:o.resource}),m.state.addListener({start:(e,t)=>{o.emit("start",{track:e,name:e.animation.name})},complete:(e,t)=>{o.emit("complete",{track:e,name:e.animation.name})},interrupt:(e,t)=>{o.emit("interrupt",{track:e,name:e.animation.name})},end:(e,t)=>{o.emit("end",{track:e,name:e.animation.name})},event:(e,t)=>{o.emit("event",e,t)}})})}change(e){this.remove(e),this.add(e)}remove(e){var n,i,r,s,a,c;return o(this,void 0,void 0,function*(){const l=e.gameObject.id;this.increaseAsyncId(l);const d=e.component;clearTimeout(d.addHandler);const u=this.armatures[l],m=null===(i=null===(n=this.renderSystem)||void 0===n?void 0:n.containerManager)||void 0===i?void 0:i.getContainer(l);m&&u&&m.removeChild(u);const h=d.armature;if(d.armature=null,delete this.armatures[l],delete this._spineComponents[l],h&&(d._destroySlotGameObjects(),h.destroyed||h.destroy({children:!0}),!d.keepResource&&d.lastResource))try{const e=yield t.resource.getResource(d.lastResource);(null===(s=null===(r=e.data)||void 0===r?void 0:r.image)||void 0===s?void 0:s.src)||(null===(c=null===(a=e.data)||void 0===a?void 0:a.image)||void 0===c||c.label);!function(e){const n=e.name,i=p[n];i&&(i.ref--,setTimeout(()=>o(this,void 0,void 0,function*(){i.ref<=0&&(t.resource.destroy(n),delete p[n])}),100))}(e)}catch(e){console.warn("Failed to release Spine resource",d.lastResource,e)}e.type,t.OBSERVER_TYPE.CHANGE})}};y.systemName="SpineSystem",y=r([t.decorators.componentObserver({Spine:["resource"]})],y);var f=y;return t.resource.registerResourceType("SPINE"),e.Spine=m,e.SpineSystem=f,Object.defineProperty(e,"__esModule",{value:!0}),e}({},EVA,EVA.plugin.renderer,PIXI);globalThis.EVA.plugin.spineBase=globalThis.EVA.plugin.spineBase||_EVA_IIFE_spineBase;
|
|
1
|
+
function _extends(){return _extends=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var s in n)({}).hasOwnProperty.call(n,s)&&(e[s]=n[s])}return e},_extends.apply(null,arguments)}globalThis.EVA=globalThis.EVA||{},globalThis.EVA.plugin=globalThis.EVA.plugin||{};var _EVA_IIFE_spineBase=function(e,t,n,s){"use strict";function o(e,t,n,s){var o,i=arguments.length,r=i<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,n):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,n,s);else for(var a=e.length-1;a>=0;a--)(o=e[a])&&(r=(i<3?o(r):i>3?o(t,n,r):o(t,n))||r);return i>3&&r&&Object.defineProperty(t,n,r),r}function i(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function r(e,t,n,s){return new(n||(n=Promise))(function(o,i){function r(e){try{l(s.next(e))}catch(e){i(e)}}function a(e){try{l(s.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(r,a)}l((s=s.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError,"function"==typeof SuppressedError&&SuppressedError;class a extends Error{constructor(){super("Symbol keys are not supported yet!"),Object.setPrototypeOf(this,new.target.prototype)}}const l="IDE_PROPERTY_METADATA";function c(e,t,n,s){let o=Reflect.getMetadata("design:type",e,t),i=o===Array;const r=function(e){return e===String?"string":e===Number?"number":e===Boolean?"boolean":"unknown"}(o);if("unknown"!==r&&(o=r),s){const e=s();Array.isArray(e)?(i=!0,o=e[0]):o=e}const a=Reflect.getMetadata(l,e.constructor)||{},c=_extends(_extends(_extends({},a[t]||{}),{type:o,isArray:i}),n);a[t]=c,Reflect.defineMetadata(l,a,e.constructor);!function(e,t,n){const s=e.constructor,o=s.IDEProps||{};o[t]=_extends(_extends({key:t},o[t]),n),s.IDEProps=o}(e,t,function(e,t){var n={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(s=Object.getOwnPropertySymbols(e);o<s.length;o++)t.indexOf(s[o])<0&&Object.prototype.propertyIsEnumerable.call(e,s[o])&&(n[s[o]]=e[s[o]])}return n}(c,["isArray"]))}function d(e){return t={type:e},(e,s)=>{if("symbol"==typeof s)throw new a;const{options:o,returnTypeFunc:i}=function(e,t){return"function"==typeof e?{returnTypeFunc:e,options:t||{}}:{options:e||{}}}(t,n);c(e,s,o,i)};var t,n}var u;!function(e){e[e.Edit=2]="Edit",e[e.Game=4]="Game",e[e.All=6]="All"}(u||(u={}));class m extends t.Component{constructor(e){super(e),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this.timeScale=1,this.skin="",this._slotGameObjects=new Map,this._pendingSlotObjects=[],this.waitExecuteInfos=[],this.listenerBound=!1,this.paused=!1,this.init(e)}set armature(e){if(this._armature=e,e){this.applyTimeScale(),this.skin&&this.setSkin(this.skin),this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:n,track:s}=e;this.play(t,n,s)}else this.stop(e.track);this.waitExecuteInfos=[],this._flushPendingSlotObjects()}}get armature(){return this._armature}init(e){e&&_extends(this,e),this.listenerBound||(this.listenerBound=!0,this.on("start",e=>{var t;null===(t=this.onStart)||void 0===t||t.call(this,e)}),this.on("complete",e=>{var t;null===(t=this.onComplete)||void 0===t||t.call(this,e)}),this.on("event",(e,t)=>{var n;null===(n=this.onEvent)||void 0===n||n.call(this,e,t)}))}onDestroy(){this.destroied=!0}load(){return this.armature}destroy(){this.onDestroy(),this._destroySlotGameObjects(),this.armature&&!this.armature.destroyed&&this.armature.destroy({children:!0}),this.armature=null}pause(){this.paused=!0,this.applyTimeScale()}resume(){this.paused=!1,this.applyTimeScale()}setSkin(e){var t,n,s,o,i;if(this.skin=e,null===(t=this.armature)||void 0===t?void 0:t.skeleton){if(this.armature.skeleton.setSkinByName)this.armature.skeleton.setSkinByName(e);else if(this.armature.skeleton.setSkin){const t=(null===(s=null===(n=this.armature.skeleton.data)||void 0===n?void 0:n.findSkin)||void 0===s?void 0:s.call(n,e))||e;this.armature.skeleton.setSkin(t)}null===(i=(o=this.armature.skeleton).setSlotsToSetupPose)||void 0===i||i.call(o)}}play(e,t,n){try{const s=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===n&&(n=0),this.applyTimeScale(),this.armature.state.setAnimation(n,this.animationName,s)):this.waitExecuteInfos.push({playType:!0,name:e,loop:s,track:n})}catch(e){console.log(e)}}stop(e){this.armature?(void 0===e&&(e=0),this.armature.state.setEmptyAnimation(e,0)):this.waitExecuteInfos.push({playType:!1,track:e})}applyTimeScale(){var e;(null===(e=this.armature)||void 0===e?void 0:e.state)&&(this.armature.state.timeScale=this.paused?0:this.timeScale)}addAnimation(e,t,n,s){try{this.armature&&(void 0===s&&(s=0),this.armature.state.addAnimation(s,e,n,t))}catch(e){console.log(e)}}setMix(e,t,n){this.armature&&this.armature.state.data.setMix(e,t,n)}getAnim(e=0){try{if(this.armature)return this.armature.state.tracks[e].animation.name}catch(e){console.log(e)}}setDefaultMix(e){this.armature&&(this.armature.state.data.defaultMix=e)}setAttachment(e,t){this.armature&&this.armature.skeleton.setAttachment(e,t)}getBone(e){if(this.armature)return this.armature.skeleton.findBone(e)}addSlotObject(e,t,n){this.destroied?console.warn("Spine component has been destroyed, cannot addSlotObject"):t&&!t.destroyed?(this._pendingSlotObjects=this._pendingSlotObjects.filter(e=>e.gameObject!==t),this._detachSlotObject(t),this._pendingSlotObjects.push({slot:e,gameObject:t,options:n}),this._flushPendingSlotObjects()):console.warn("Cannot add a destroyed or missing GameObject to a Spine slot")}_doAddSlotObject(e,t,n,o){const i=new s.Container;i.addChild(n),this.armature.addSlotObject(e,i,o),this._slotGameObjects.set(t,{slot:e,wrapper:i}),this._syncTransformTree(t)}_isSlotAvailable(e){var t,n,s,o;if("number"==typeof e){if(!Number.isInteger(e)||e<0)return!1;const s=null===(n=null===(t=this.armature)||void 0===t?void 0:t.skeleton)||void 0===n?void 0:n.slots;return!Array.isArray(s)||e<s.length}if("string"!=typeof e||0===e.length)return!1;const i=null===(o=null===(s=this.armature)||void 0===s?void 0:s.skeleton)||void 0===o?void 0:o.findSlot;return"function"!=typeof i||Boolean(i.call(this.armature.skeleton,e))}_detachSlotObject(e){const t=this._slotGameObjects.get(e);if(t){this.armature&&!this.armature.destroyed&&this.armature.removeSlotObject(t.wrapper);for(const e of[...t.wrapper.children])t.wrapper.removeChild(e);t.wrapper.destroy({children:!1}),this._slotGameObjects.delete(e)}}_syncTransformTree(e){var t;if(this._containerManager&&(this._containerManager.updateTransform({name:e.id,transform:e.transform}),null===(t=e.transform)||void 0===t?void 0:t.children))for(const t of e.transform.children)t.gameObject&&this._syncTransformTree(t.gameObject)}_flushPendingSlotObjects(){if(this.destroied||0===this._pendingSlotObjects.length)return;if(!this.armature||!this._containerManager)return;const e=[],t=this._pendingSlotObjects;this._pendingSlotObjects=[];for(const n of t){if(n.gameObject.destroyed)continue;if(!this._isSlotAvailable(n.slot)){console.warn(`Spine slot "${n.slot}" does not exist; pending slot object was discarded`);continue}const t=this._containerManager.getContainer(n.gameObject.id);if(t)try{this._doAddSlotObject(n.slot,n.gameObject,t,n.options)}catch(e){console.warn(`Failed to add GameObject to Spine slot "${n.slot}"`,e)}else e.push(n)}this._pendingSlotObjects.push(...e)}removeSlotObject(e){this._pendingSlotObjects=this._pendingSlotObjects.filter(t=>t.gameObject!==e),this._detachSlotObject(e)}_destroySlotGameObjects(){const e=new Set([...this._slotGameObjects.keys(),...this._pendingSlotObjects.map(e=>e.gameObject)]);for(const t of e)this._detachSlotObject(t),t.destroyed||t.destroy();this._slotGameObjects.clear(),this._pendingSlotObjects=[]}}m.componentName="Spine",o([d("string"),i("design:type",String)],m.prototype,"resource",void 0),o([d("number"),i("design:type",Number)],m.prototype,"scale",void 0),o([d("string"),i("design:type",String)],m.prototype,"animationName",void 0),o([d("boolean"),i("design:type",Boolean)],m.prototype,"autoPlay",void 0),o([d("boolean"),i("design:type",Boolean)],m.prototype,"keepResource",void 0),o([d("number"),i("design:type",Number)],m.prototype,"timeScale",void 0),o([d("string"),i("design:type",String)],m.prototype,"skin",void 0);let h={};function p(e,t,n){return r(this,void 0,void 0,function*(){let s=h[e.name];if(!s)if(e.complete)s=function(e,t,n,s){const o=t.ske,i=t.atlas,r=new s.AtlasAttachmentLoader(i),a=o instanceof Uint8Array?new s.SkeletonBinary(r):new s.SkeletonJson(r);a.scale=n||1;const l={spineData:a.readSkeletonData(o),ref:0,imageSrc:(c=t.image,c?"string"==typeof c?c:c.label||(null===(d=c.source)||void 0===d?void 0:d.label)||(null===(m=null===(u=c.source)||void 0===u?void 0:u.resource)||void 0===m?void 0:m.src)||(null===(p=c.source)||void 0===p?void 0:p._sourceOrigin)||c.src||(null===(f=c.baseTexture)||void 0===f?void 0:f.cacheId)||"":"")};var c,d,u,m,p,f;return h[e]=l,l}(e.name,e.data,t,n);else if(!s)return;return s.ref++,s.spineData})}let f=class extends n.Renderer{constructor(){super(...arguments),this.armatures={},this._spineComponents={}}init({pixiSpine:e}){this.renderSystem=this.game.getSystem(n.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=e,this.game.canvas.addEventListener("webglcontextrestored",()=>{const e=this.game.gameObjects;let n=[];for(let s in this.armatures){const o=+s;for(let s=0;s<e.length;++s){let i=e[s];if(i.id===o){let e=i.getComponent(m);e&&(this.remove({type:t.OBSERVER_TYPE.REMOVE,gameObject:i,component:e,componentName:m.componentName}),n.push({type:t.OBSERVER_TYPE.ADD,gameObject:i,component:e,componentName:m.componentName}));break}}}setTimeout(()=>{n.forEach(e=>{this.add(e)})},1e3)},!1)}update(e){super.update();for(let t in this.armatures){const n=this.armatures[t],s=this._spineComponents[t];!n||n.destroyed||(null==s?void 0:s.destroied)?(this.releaseComponentResource(s),delete this.armatures[t],delete this._spineComponents[t]):n.update(.001*e.deltaTime)}for(let e in this._spineComponents){const t=this._spineComponents[e];t&&!t.destroied?t._flushPendingSlotObjects():(this.releaseComponentResource(t),delete this._spineComponents[e])}}componentChanged(e){return r(this,void 0,void 0,function*(){if("Spine"===e.componentName)if(e.type===t.OBSERVER_TYPE.ADD)this.add(e);else if(e.type===t.OBSERVER_TYPE.CHANGE){if("resource"===e.prop.prop[0])this.change(e)}else e.type===t.OBSERVER_TYPE.REMOVE&&this.remove(e)})}add(e,n){var s,o,i;return r(this,void 0,void 0,function*(){const r=e.component;clearTimeout(r.addHandler);const a=e.gameObject.id,l=this.increaseAsyncId(a),c=yield t.resource.getResource(r.resource);if(!this.validateAsyncId(a,l)||r.destroied||e.gameObject.destroyed)return;const d=yield p(c,r.scale,this.pixiSpine);if(!this.validateAsyncId(a,l)||r.destroied||e.gameObject.destroyed)return;if(!d)return void(r.addHandler=setTimeout(()=>{r.destroied||e.gameObject.destroyed||(void 0===n&&(n=20),--n>0?this.add(e,n):console.log("retry exceed max times",r.resource))},1e3));this.remove(e);const u=null===(o=null===(s=this.renderSystem)||void 0===s?void 0:s.containerManager)||void 0===o?void 0:o.getContainer(e.gameObject.id);if(!u||r.destroied||e.gameObject.destroyed)return;r.lastResource=r.resource;const m=new this.pixiSpine.Spine({skeletonData:d,autoUpdate:!1});if(this.armatures[e.gameObject.id]=m,this._spineComponents[e.gameObject.id]=r,e.gameObject&&e.gameObject.transform){const t=e.gameObject.transform;m.x=t.size.width*t.origin.x,m.y=t.size.height*t.origin.y}u.addChildAt(m,0),m.update(),r._containerManager=null===(i=this.renderSystem)||void 0===i?void 0:i.containerManager,r.armature=m,r.emit("loaded",{resource:r.resource}),m.state.addListener({start:(e,t)=>{r.emit("start",{track:e,name:e.animation.name})},complete:(e,t)=>{r.emit("complete",{track:e,name:e.animation.name})},interrupt:(e,t)=>{r.emit("interrupt",{track:e,name:e.animation.name})},end:(e,t)=>{r.emit("end",{track:e,name:e.animation.name})},event:(e,t)=>{r.emit("event",e,t)}})})}change(e){this.remove(e),this.add(e)}remove(e){var n,s;return r(this,void 0,void 0,function*(){const o=e.gameObject.id;this.increaseAsyncId(o);const i=e.component;clearTimeout(i.addHandler);const r=this.armatures[o],a=null===(s=null===(n=this.renderSystem)||void 0===n?void 0:n.containerManager)||void 0===s?void 0:s.getContainer(o);a&&r&&a.removeChild(r);const l=i.armature;i.armature=null,delete this.armatures[o],delete this._spineComponents[o],l&&(i._destroySlotGameObjects(),l.destroyed||l.destroy({children:!0})),this.releaseComponentResource(i),e.type,t.OBSERVER_TYPE.CHANGE})}onDestroy(){for(const e of Object.keys(this._spineComponents)){const t=this._spineComponents[+e],n=this.armatures[+e];null==t||t._destroySlotGameObjects(),n&&!n.destroyed&&n.destroy({children:!0}),t&&(t.armature=null),this.releaseComponentResource(t)}this.armatures={},this._spineComponents={},this.asyncIdMap={}}releaseComponentResource(e){const n=null==e?void 0:e.lastResource;e&&n&&(e.lastResource="",function(e,n,s=!0){const o=e.name,i=h[o];i&&(i.ref--,i.ref>0||(h[o]===i&&delete h[o],s&&setTimeout(()=>r(this,void 0,void 0,function*(){i.ref<=0&&!h[o]&&t.resource.destroy(o)}),100)))}({name:n},0,!e.keepResource))}};f.systemName="SpineSystem",f=o([t.decorators.componentObserver({Spine:["resource"]})],f);var y=f;return t.resource.registerResourceType("SPINE"),e.Spine=m,e.SpineSystem=y,Object.defineProperty(e,"__esModule",{value:!0}),e}({},EVA,EVA.plugin.renderer,PIXI);globalThis.EVA.plugin.spineBase=globalThis.EVA.plugin.spineBase||_EVA_IIFE_spineBase;
|
package/dist/spine-base.cjs.js
CHANGED
|
@@ -119,7 +119,7 @@ class Spine extends eva_js.Component {
|
|
|
119
119
|
this.timeScale = 1;
|
|
120
120
|
/** 当前皮肤名称 */
|
|
121
121
|
this.skin = '';
|
|
122
|
-
/** 挂载到插槽的 GameObject
|
|
122
|
+
/** 挂载到插槽的 GameObject 及对应 slot/wrapper 映射 */
|
|
123
123
|
this._slotGameObjects = new Map();
|
|
124
124
|
/** 等待容器就绪的 slot 挂载请求 */
|
|
125
125
|
this._pendingSlotObjects = [];
|
|
@@ -129,10 +129,7 @@ class Spine extends eva_js.Component {
|
|
|
129
129
|
this.paused = false;
|
|
130
130
|
this.init(params);
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
* 设置骨架实例
|
|
134
|
-
* 当骨架加载完成后自动执行等待队列中的动画操作
|
|
135
|
-
*/
|
|
132
|
+
// 设置骨架实例;骨架加载完成后自动执行等待队列中的动画操作。
|
|
136
133
|
set armature(val) {
|
|
137
134
|
this._armature = val;
|
|
138
135
|
if (!val)
|
|
@@ -153,6 +150,7 @@ class Spine extends eva_js.Component {
|
|
|
153
150
|
}
|
|
154
151
|
}
|
|
155
152
|
this.waitExecuteInfos = [];
|
|
153
|
+
this._flushPendingSlotObjects();
|
|
156
154
|
}
|
|
157
155
|
/** 获取骨架实例 */
|
|
158
156
|
get armature() {
|
|
@@ -194,8 +192,8 @@ class Spine extends eva_js.Component {
|
|
|
194
192
|
}
|
|
195
193
|
destroy() {
|
|
196
194
|
this.onDestroy();
|
|
195
|
+
this._destroySlotGameObjects();
|
|
197
196
|
if (this.armature && !this.armature.destroyed) {
|
|
198
|
-
this._destroySlotGameObjects();
|
|
199
197
|
this.armature.destroy({ children: true });
|
|
200
198
|
}
|
|
201
199
|
this.armature = null;
|
|
@@ -399,21 +397,19 @@ class Spine extends eva_js.Component {
|
|
|
399
397
|
* @param options.followAttachmentTimeline - 是否跟随插槽的附件时间线
|
|
400
398
|
*/
|
|
401
399
|
addSlotObject(slot, gameObject, options) {
|
|
402
|
-
if (
|
|
403
|
-
console.warn('Spine
|
|
400
|
+
if (this.destroied) {
|
|
401
|
+
console.warn('Spine component has been destroyed, cannot addSlotObject');
|
|
404
402
|
return;
|
|
405
403
|
}
|
|
406
|
-
if (!
|
|
407
|
-
console.warn('
|
|
404
|
+
if (!gameObject || gameObject.destroyed) {
|
|
405
|
+
console.warn('Cannot add a destroyed or missing GameObject to a Spine slot');
|
|
408
406
|
return;
|
|
409
407
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
this._doAddSlotObject(slot, gameObject, container, options);
|
|
408
|
+
// 同一 GameObject 只保留最后一次挂载意图,避免依赖分阶段就绪时重复挂载。
|
|
409
|
+
this._pendingSlotObjects = this._pendingSlotObjects.filter(pending => pending.gameObject !== gameObject);
|
|
410
|
+
this._detachSlotObject(gameObject);
|
|
411
|
+
this._pendingSlotObjects.push({ slot, gameObject, options });
|
|
412
|
+
this._flushPendingSlotObjects();
|
|
417
413
|
}
|
|
418
414
|
_doAddSlotObject(slot, gameObject, container, options) {
|
|
419
415
|
// 创建 wrapper 容器:Spine 骨骼矩阵作用在 wrapper 上,
|
|
@@ -426,6 +422,32 @@ class Spine extends eva_js.Component {
|
|
|
426
422
|
// 手动同步 gameObject 及其子树的 transform 到 container
|
|
427
423
|
this._syncTransformTree(gameObject);
|
|
428
424
|
}
|
|
425
|
+
_isSlotAvailable(slot) {
|
|
426
|
+
var _a, _b, _c, _d;
|
|
427
|
+
if (typeof slot === 'number') {
|
|
428
|
+
if (!Number.isInteger(slot) || slot < 0)
|
|
429
|
+
return false;
|
|
430
|
+
const slots = (_b = (_a = this.armature) === null || _a === void 0 ? void 0 : _a.skeleton) === null || _b === void 0 ? void 0 : _b.slots;
|
|
431
|
+
return !Array.isArray(slots) || slot < slots.length;
|
|
432
|
+
}
|
|
433
|
+
if (typeof slot !== 'string' || slot.length === 0)
|
|
434
|
+
return false;
|
|
435
|
+
const findSlot = (_d = (_c = this.armature) === null || _c === void 0 ? void 0 : _c.skeleton) === null || _d === void 0 ? void 0 : _d.findSlot;
|
|
436
|
+
return typeof findSlot !== 'function' || Boolean(findSlot.call(this.armature.skeleton, slot));
|
|
437
|
+
}
|
|
438
|
+
_detachSlotObject(gameObject) {
|
|
439
|
+
const entry = this._slotGameObjects.get(gameObject);
|
|
440
|
+
if (!entry)
|
|
441
|
+
return;
|
|
442
|
+
if (this.armature && !this.armature.destroyed) {
|
|
443
|
+
this.armature.removeSlotObject(entry.wrapper);
|
|
444
|
+
}
|
|
445
|
+
for (const child of [...entry.wrapper.children]) {
|
|
446
|
+
entry.wrapper.removeChild(child);
|
|
447
|
+
}
|
|
448
|
+
entry.wrapper.destroy({ children: false });
|
|
449
|
+
this._slotGameObjects.delete(gameObject);
|
|
450
|
+
}
|
|
429
451
|
/**
|
|
430
452
|
* 递归同步 gameObject 及其子树的 transform 到对应的渲染容器
|
|
431
453
|
*/
|
|
@@ -449,21 +471,34 @@ class Spine extends eva_js.Component {
|
|
|
449
471
|
* 处理等待容器就绪的 slot 挂载请求(由 SpineSystem 每帧调用)
|
|
450
472
|
*/
|
|
451
473
|
_flushPendingSlotObjects() {
|
|
452
|
-
if (this._pendingSlotObjects.length === 0)
|
|
474
|
+
if (this.destroied || this._pendingSlotObjects.length === 0)
|
|
453
475
|
return;
|
|
454
476
|
if (!this.armature || !this._containerManager)
|
|
455
477
|
return;
|
|
456
478
|
const still = [];
|
|
457
|
-
|
|
479
|
+
const pendingSlotObjects = this._pendingSlotObjects;
|
|
480
|
+
this._pendingSlotObjects = [];
|
|
481
|
+
for (const pending of pendingSlotObjects) {
|
|
482
|
+
if (pending.gameObject.destroyed)
|
|
483
|
+
continue;
|
|
484
|
+
if (!this._isSlotAvailable(pending.slot)) {
|
|
485
|
+
console.warn(`Spine slot "${pending.slot}" does not exist; pending slot object was discarded`);
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
458
488
|
const container = this._containerManager.getContainer(pending.gameObject.id);
|
|
459
489
|
if (container) {
|
|
460
|
-
|
|
490
|
+
try {
|
|
491
|
+
this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
console.warn(`Failed to add GameObject to Spine slot "${pending.slot}"`, error);
|
|
495
|
+
}
|
|
461
496
|
}
|
|
462
497
|
else {
|
|
463
498
|
still.push(pending);
|
|
464
499
|
}
|
|
465
500
|
}
|
|
466
|
-
this._pendingSlotObjects
|
|
501
|
+
this._pendingSlotObjects.push(...still);
|
|
467
502
|
}
|
|
468
503
|
/**
|
|
469
504
|
* 从插槽上移除挂载的 GameObject
|
|
@@ -473,24 +508,19 @@ class Spine extends eva_js.Component {
|
|
|
473
508
|
removeSlotObject(gameObject) {
|
|
474
509
|
// 从 pending 队列中移除
|
|
475
510
|
this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
|
|
476
|
-
|
|
477
|
-
if (entry && this.armature) {
|
|
478
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
479
|
-
entry.wrapper.destroy({ children: false });
|
|
480
|
-
}
|
|
481
|
-
this._slotGameObjects.delete(gameObject);
|
|
511
|
+
this._detachSlotObject(gameObject);
|
|
482
512
|
}
|
|
483
513
|
/**
|
|
484
514
|
* 销毁所有挂载到插槽的 GameObject(内部使用)
|
|
485
515
|
*/
|
|
486
516
|
_destroySlotGameObjects() {
|
|
487
|
-
|
|
517
|
+
const gameObjects = new Set([
|
|
518
|
+
...this._slotGameObjects.keys(),
|
|
519
|
+
...this._pendingSlotObjects.map(pending => pending.gameObject),
|
|
520
|
+
]);
|
|
521
|
+
for (const gameObject of gameObjects) {
|
|
522
|
+
this._detachSlotObject(gameObject);
|
|
488
523
|
if (!gameObject.destroyed) {
|
|
489
|
-
// 先从 spine 插槽移除 wrapper,避免 destroy 时重复操作
|
|
490
|
-
if (this.armature) {
|
|
491
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
492
|
-
}
|
|
493
|
-
entry.wrapper.destroy({ children: false });
|
|
494
524
|
gameObject.destroy();
|
|
495
525
|
}
|
|
496
526
|
}
|
|
@@ -574,17 +604,31 @@ function getSpineData(res, scale, pixiSpine) {
|
|
|
574
604
|
return data.spineData;
|
|
575
605
|
});
|
|
576
606
|
}
|
|
577
|
-
function releaseSpineData(res, _imageSrc) {
|
|
607
|
+
function releaseSpineData(res, _imageSrc, destroyResource = true) {
|
|
578
608
|
const resourceName = res.name;
|
|
579
609
|
const data = dataMap[resourceName];
|
|
580
610
|
if (!data) {
|
|
581
611
|
return;
|
|
582
612
|
}
|
|
583
613
|
data.ref--;
|
|
614
|
+
if (data.ref > 0) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
// Parsed skeleton data owns attachment objects that point at Pixi textures.
|
|
618
|
+
// Armature teardown can invalidate those objects even when the raw resource
|
|
619
|
+
// is intentionally kept. Remove this generation immediately so the next
|
|
620
|
+
// EvaApp reparses the still-loaded atlas instead of rendering stale sources.
|
|
621
|
+
if (dataMap[resourceName] === data) {
|
|
622
|
+
delete dataMap[resourceName];
|
|
623
|
+
}
|
|
624
|
+
if (!destroyResource) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
584
627
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
585
|
-
|
|
628
|
+
// A newer EvaApp may have rebuilt the same resource name while this delayed
|
|
629
|
+
// release was pending. Never unload the replacement generation's assets.
|
|
630
|
+
if (data.ref <= 0 && !dataMap[resourceName]) {
|
|
586
631
|
eva_js.resource.destroy(resourceName);
|
|
587
|
-
delete dataMap[resourceName];
|
|
588
632
|
}
|
|
589
633
|
}), 100);
|
|
590
634
|
}
|
|
@@ -667,6 +711,7 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
|
|
|
667
711
|
const armature = this.armatures[key];
|
|
668
712
|
const component = this._spineComponents[key];
|
|
669
713
|
if (!armature || armature.destroyed || (component === null || component === void 0 ? void 0 : component.destroied)) {
|
|
714
|
+
this.releaseComponentResource(component);
|
|
670
715
|
delete this.armatures[key];
|
|
671
716
|
delete this._spineComponents[key];
|
|
672
717
|
continue;
|
|
@@ -679,6 +724,7 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
|
|
|
679
724
|
for (let key in this._spineComponents) {
|
|
680
725
|
const component = this._spineComponents[key];
|
|
681
726
|
if (!component || component.destroied) {
|
|
727
|
+
this.releaseComponentResource(component);
|
|
682
728
|
delete this._spineComponents[key];
|
|
683
729
|
continue;
|
|
684
730
|
}
|
|
@@ -790,7 +836,7 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
|
|
|
790
836
|
this.add(changed);
|
|
791
837
|
}
|
|
792
838
|
remove(changed) {
|
|
793
|
-
var _a, _b
|
|
839
|
+
var _a, _b;
|
|
794
840
|
return __awaiter(this, void 0, void 0, function* () {
|
|
795
841
|
const gameObjectId = changed.gameObject.id;
|
|
796
842
|
this.increaseAsyncId(gameObjectId);
|
|
@@ -811,20 +857,36 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
|
|
|
811
857
|
if (!componentArmature.destroyed) {
|
|
812
858
|
componentArmature.destroy({ children: true });
|
|
813
859
|
}
|
|
814
|
-
if (!component.keepResource && component.lastResource) {
|
|
815
|
-
try {
|
|
816
|
-
const res = yield eva_js.resource.getResource(component.lastResource);
|
|
817
|
-
const imageSrc = ((_d = (_c = res.data) === null || _c === void 0 ? void 0 : _c.image) === null || _d === void 0 ? void 0 : _d.src) || ((_f = (_e = res.data) === null || _e === void 0 ? void 0 : _e.image) === null || _f === void 0 ? void 0 : _f.label);
|
|
818
|
-
releaseSpineData(res, imageSrc);
|
|
819
|
-
}
|
|
820
|
-
catch (error) {
|
|
821
|
-
console.warn('Failed to release Spine resource', component.lastResource, error);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
860
|
}
|
|
861
|
+
this.releaseComponentResource(component);
|
|
825
862
|
if (changed.type === eva_js.OBSERVER_TYPE.CHANGE) ;
|
|
826
863
|
});
|
|
827
864
|
}
|
|
865
|
+
onDestroy() {
|
|
866
|
+
for (const key of Object.keys(this._spineComponents)) {
|
|
867
|
+
const component = this._spineComponents[+key];
|
|
868
|
+
const armature = this.armatures[+key];
|
|
869
|
+
component === null || component === void 0 ? void 0 : component._destroySlotGameObjects();
|
|
870
|
+
if (armature && !armature.destroyed) {
|
|
871
|
+
armature.destroy({ children: true });
|
|
872
|
+
}
|
|
873
|
+
if (component) {
|
|
874
|
+
component.armature = null;
|
|
875
|
+
}
|
|
876
|
+
this.releaseComponentResource(component);
|
|
877
|
+
}
|
|
878
|
+
this.armatures = {};
|
|
879
|
+
this._spineComponents = {};
|
|
880
|
+
this.asyncIdMap = {};
|
|
881
|
+
}
|
|
882
|
+
releaseComponentResource(component) {
|
|
883
|
+
const resourceName = component === null || component === void 0 ? void 0 : component.lastResource;
|
|
884
|
+
if (!component || !resourceName) {
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
component.lastResource = '';
|
|
888
|
+
releaseSpineData({ name: resourceName }, '', !component.keepResource);
|
|
889
|
+
}
|
|
828
890
|
};
|
|
829
891
|
/** 系统名称 */
|
|
830
892
|
SpineSystem.systemName = 'SpineSystem';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@eva/eva.js"),t=require("@eva/plugin-renderer"),i=require("pixi.js"),s=require("@eva/inspector-decorator");function r(e,t,i,s){var r,n=arguments.length,a=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,s);else for(var o=e.length-1;o>=0;o--)(r=e[o])&&(a=(n<3?r(a):n>3?r(t,i,a):r(t,i))||a);return n>3&&a&&Object.defineProperty(t,i,a),a}function n(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function a(e,t,i,s){return new(i||(i=Promise))(function(r,n){function a(e){try{c(s.next(e))}catch(e){n(e)}}function o(e){try{c(s.throw(e))}catch(e){n(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof i?t:new i(function(e){e(t)})).then(a,o)}c((s=s.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class o extends e.Component{constructor(e){super(e),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this.timeScale=1,this.skin="",this._slotGameObjects=new Map,this._pendingSlotObjects=[],this.waitExecuteInfos=[],this.listenerBound=!1,this.paused=!1,this.init(e)}set armature(e){if(this._armature=e,e){this.applyTimeScale(),this.skin&&this.setSkin(this.skin),this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:i,track:s}=e;this.play(t,i,s)}else this.stop(e.track);this.waitExecuteInfos=[]}}get armature(){return this._armature}init(e){e&&Object.assign(this,e),this.listenerBound||(this.listenerBound=!0,this.on("start",e=>{var t;null===(t=this.onStart)||void 0===t||t.call(this,e)}),this.on("complete",e=>{var t;null===(t=this.onComplete)||void 0===t||t.call(this,e)}),this.on("event",(e,t)=>{var i;null===(i=this.onEvent)||void 0===i||i.call(this,e,t)}))}onDestroy(){this.destroied=!0}load(){return this.armature}destroy(){this.onDestroy(),this.armature&&!this.armature.destroyed&&(this._destroySlotGameObjects(),this.armature.destroy({children:!0})),this.armature=null}pause(){this.paused=!0,this.applyTimeScale()}resume(){this.paused=!1,this.applyTimeScale()}setSkin(e){var t,i,s,r,n;if(this.skin=e,null===(t=this.armature)||void 0===t?void 0:t.skeleton){if(this.armature.skeleton.setSkinByName)this.armature.skeleton.setSkinByName(e);else if(this.armature.skeleton.setSkin){const t=(null===(s=null===(i=this.armature.skeleton.data)||void 0===i?void 0:i.findSkin)||void 0===s?void 0:s.call(i,e))||e;this.armature.skeleton.setSkin(t)}null===(n=(r=this.armature.skeleton).setSlotsToSetupPose)||void 0===n||n.call(r)}}play(e,t,i){try{const s=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===i&&(i=0),this.applyTimeScale(),this.armature.state.setAnimation(i,this.animationName,s)):this.waitExecuteInfos.push({playType:!0,name:e,loop:s,track:i})}catch(e){console.log(e)}}stop(e){this.armature?(void 0===e&&(e=0),this.armature.state.setEmptyAnimation(e,0)):this.waitExecuteInfos.push({playType:!1,track:e})}applyTimeScale(){var e;(null===(e=this.armature)||void 0===e?void 0:e.state)&&(this.armature.state.timeScale=this.paused?0:this.timeScale)}addAnimation(e,t,i,s){try{this.armature&&(void 0===s&&(s=0),this.armature.state.addAnimation(s,e,i,t))}catch(e){console.log(e)}}setMix(e,t,i){this.armature&&this.armature.state.data.setMix(e,t,i)}getAnim(e=0){try{if(this.armature)return this.armature.state.tracks[e].animation.name}catch(e){console.log(e)}}setDefaultMix(e){this.armature&&(this.armature.state.data.defaultMix=e)}setAttachment(e,t){this.armature&&this.armature.skeleton.setAttachment(e,t)}getBone(e){if(this.armature)return this.armature.skeleton.findBone(e)}addSlotObject(e,t,i){if(!this.armature)return void console.warn("Spine armature is not ready, cannot addSlotObject");if(!this._containerManager)return void console.warn("ContainerManager is not available");const s=this._containerManager.getContainer(t.id);s?this._doAddSlotObject(e,t,s,i):this._pendingSlotObjects.push({slot:e,gameObject:t,options:i})}_doAddSlotObject(e,t,s,r){const n=new i.Container;n.addChild(s),this.armature.addSlotObject(e,n,r),this._slotGameObjects.set(t,{slot:e,wrapper:n}),this._syncTransformTree(t)}_syncTransformTree(e){var t;if(this._containerManager&&(this._containerManager.updateTransform({name:e.id,transform:e.transform}),null===(t=e.transform)||void 0===t?void 0:t.children))for(const t of e.transform.children)t.gameObject&&this._syncTransformTree(t.gameObject)}_flushPendingSlotObjects(){if(0===this._pendingSlotObjects.length)return;if(!this.armature||!this._containerManager)return;const e=[];for(const t of this._pendingSlotObjects){const i=this._containerManager.getContainer(t.gameObject.id);i?this._doAddSlotObject(t.slot,t.gameObject,i,t.options):e.push(t)}this._pendingSlotObjects=e}removeSlotObject(e){this._pendingSlotObjects=this._pendingSlotObjects.filter(t=>t.gameObject!==e);const t=this._slotGameObjects.get(e);t&&this.armature&&(this.armature.removeSlotObject(t.wrapper),t.wrapper.destroy({children:!1})),this._slotGameObjects.delete(e)}_destroySlotGameObjects(){for(const[e,t]of this._slotGameObjects)e.destroyed||(this.armature&&this.armature.removeSlotObject(t.wrapper),t.wrapper.destroy({children:!1}),e.destroy());this._slotGameObjects.clear(),this._pendingSlotObjects=[]}}o.componentName="Spine",r([s.type("string"),n("design:type",String)],o.prototype,"resource",void 0),r([s.type("number"),n("design:type",Number)],o.prototype,"scale",void 0),r([s.type("string"),n("design:type",String)],o.prototype,"animationName",void 0),r([s.type("boolean"),n("design:type",Boolean)],o.prototype,"autoPlay",void 0),r([s.type("boolean"),n("design:type",Boolean)],o.prototype,"keepResource",void 0),r([s.type("number"),n("design:type",Number)],o.prototype,"timeScale",void 0),r([s.type("string"),n("design:type",String)],o.prototype,"skin",void 0);let c={};function d(e,t,i){return a(this,void 0,void 0,function*(){let s=c[e.name];if(!s)if(e.complete)s=function(e,t,i,s){const r=t.ske,n=t.atlas,a=new s.AtlasAttachmentLoader(n),o=r instanceof Uint8Array?new s.SkeletonBinary(a):new s.SkeletonJson(a);o.scale=i||1;const d={spineData:o.readSkeletonData(r),ref:0,imageSrc:(l=t.image,l?"string"==typeof l?l:l.label||(null===(m=l.source)||void 0===m?void 0:m.label)||(null===(h=null===(u=l.source)||void 0===u?void 0:u.resource)||void 0===h?void 0:h.src)||(null===(p=l.source)||void 0===p?void 0:p._sourceOrigin)||l.src||(null===(y=l.baseTexture)||void 0===y?void 0:y.cacheId)||"":"")};var l,m,u,h,p,y;return c[e]=d,d}(e.name,e.data,t,i);else if(!s)return;return s.ref++,s.spineData})}let l=class extends t.Renderer{constructor(){super(...arguments),this.armatures={},this._spineComponents={}}init({pixiSpine:i}){this.renderSystem=this.game.getSystem(t.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=i,this.game.canvas.addEventListener("webglcontextrestored",()=>{const t=this.game.gameObjects;let i=[];for(let s in this.armatures){const r=+s;for(let s=0;s<t.length;++s){let n=t[s];if(n.id===r){let t=n.getComponent(o);t&&(this.remove({type:e.OBSERVER_TYPE.REMOVE,gameObject:n,component:t,componentName:o.componentName}),i.push({type:e.OBSERVER_TYPE.ADD,gameObject:n,component:t,componentName:o.componentName}));break}}}setTimeout(()=>{i.forEach(e=>{this.add(e)})},1e3)},!1)}update(e){super.update();for(let t in this.armatures){const i=this.armatures[t],s=this._spineComponents[t];!i||i.destroyed||(null==s?void 0:s.destroied)?(delete this.armatures[t],delete this._spineComponents[t]):i.update(.001*e.deltaTime)}for(let e in this._spineComponents){const t=this._spineComponents[e];t&&!t.destroied?t._flushPendingSlotObjects():delete this._spineComponents[e]}}componentChanged(t){return a(this,void 0,void 0,function*(){if("Spine"===t.componentName)if(t.type===e.OBSERVER_TYPE.ADD)this.add(t);else if(t.type===e.OBSERVER_TYPE.CHANGE){if("resource"===t.prop.prop[0])this.change(t)}else t.type===e.OBSERVER_TYPE.REMOVE&&this.remove(t)})}add(t,i){var s,r,n;return a(this,void 0,void 0,function*(){const a=t.component;clearTimeout(a.addHandler);const o=t.gameObject.id,c=this.increaseAsyncId(o),l=yield e.resource.getResource(a.resource);if(!this.validateAsyncId(o,c)||a.destroied||t.gameObject.destroyed)return;const m=yield d(l,a.scale,this.pixiSpine);if(!this.validateAsyncId(o,c)||a.destroied||t.gameObject.destroyed)return;if(!m)return void(a.addHandler=setTimeout(()=>{a.destroied||t.gameObject.destroyed||(void 0===i&&(i=20),--i>0?this.add(t,i):console.log("retry exceed max times",a.resource))},1e3));this.remove(t);const u=null===(r=null===(s=this.renderSystem)||void 0===s?void 0:s.containerManager)||void 0===r?void 0:r.getContainer(t.gameObject.id);if(!u||a.destroied||t.gameObject.destroyed)return;a.lastResource=a.resource;const h=new this.pixiSpine.Spine({skeletonData:m,autoUpdate:!1});if(this.armatures[t.gameObject.id]=h,this._spineComponents[t.gameObject.id]=a,t.gameObject&&t.gameObject.transform){const e=t.gameObject.transform;h.x=e.size.width*e.origin.x,h.y=e.size.height*e.origin.y}u.addChildAt(h,0),h.update(),a._containerManager=null===(n=this.renderSystem)||void 0===n?void 0:n.containerManager,a.armature=h,a.emit("loaded",{resource:a.resource}),h.state.addListener({start:(e,t)=>{a.emit("start",{track:e,name:e.animation.name})},complete:(e,t)=>{a.emit("complete",{track:e,name:e.animation.name})},interrupt:(e,t)=>{a.emit("interrupt",{track:e,name:e.animation.name})},end:(e,t)=>{a.emit("end",{track:e,name:e.animation.name})},event:(e,t)=>{a.emit("event",e,t)}})})}change(e){this.remove(e),this.add(e)}remove(t){var i,s,r,n,o,d;return a(this,void 0,void 0,function*(){const l=t.gameObject.id;this.increaseAsyncId(l);const m=t.component;clearTimeout(m.addHandler);const u=this.armatures[l],h=null===(s=null===(i=this.renderSystem)||void 0===i?void 0:i.containerManager)||void 0===s?void 0:s.getContainer(l);h&&u&&h.removeChild(u);const p=m.armature;if(m.armature=null,delete this.armatures[l],delete this._spineComponents[l],p&&(m._destroySlotGameObjects(),p.destroyed||p.destroy({children:!0}),!m.keepResource&&m.lastResource))try{const t=yield e.resource.getResource(m.lastResource);(null===(n=null===(r=t.data)||void 0===r?void 0:r.image)||void 0===n?void 0:n.src)||(null===(d=null===(o=t.data)||void 0===o?void 0:o.image)||void 0===d||d.label);!function(t){const i=t.name,s=c[i];s&&(s.ref--,setTimeout(()=>a(this,void 0,void 0,function*(){s.ref<=0&&(e.resource.destroy(i),delete c[i])}),100))}(t)}catch(e){console.warn("Failed to release Spine resource",m.lastResource,e)}t.type,e.OBSERVER_TYPE.CHANGE})}};l.systemName="SpineSystem",l=r([e.decorators.componentObserver({Spine:["resource"]})],l);var m=l;e.resource.registerResourceType("SPINE"),exports.Spine=o,exports.SpineSystem=m;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@eva/eva.js"),t=require("@eva/plugin-renderer"),s=require("pixi.js"),i=require("@eva/inspector-decorator");function n(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r}function o(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function r(e,t,s,i){return new(s||(s=Promise))(function(n,o){function r(e){try{c(i.next(e))}catch(e){o(e)}}function a(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?n(e.value):(t=e.value,t instanceof s?t:new s(function(e){e(t)})).then(r,a)}c((i=i.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class a extends e.Component{constructor(e){super(e),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this.timeScale=1,this.skin="",this._slotGameObjects=new Map,this._pendingSlotObjects=[],this.waitExecuteInfos=[],this.listenerBound=!1,this.paused=!1,this.init(e)}set armature(e){if(this._armature=e,e){this.applyTimeScale(),this.skin&&this.setSkin(this.skin),this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:s,track:i}=e;this.play(t,s,i)}else this.stop(e.track);this.waitExecuteInfos=[],this._flushPendingSlotObjects()}}get armature(){return this._armature}init(e){e&&Object.assign(this,e),this.listenerBound||(this.listenerBound=!0,this.on("start",e=>{var t;null===(t=this.onStart)||void 0===t||t.call(this,e)}),this.on("complete",e=>{var t;null===(t=this.onComplete)||void 0===t||t.call(this,e)}),this.on("event",(e,t)=>{var s;null===(s=this.onEvent)||void 0===s||s.call(this,e,t)}))}onDestroy(){this.destroied=!0}load(){return this.armature}destroy(){this.onDestroy(),this._destroySlotGameObjects(),this.armature&&!this.armature.destroyed&&this.armature.destroy({children:!0}),this.armature=null}pause(){this.paused=!0,this.applyTimeScale()}resume(){this.paused=!1,this.applyTimeScale()}setSkin(e){var t,s,i,n,o;if(this.skin=e,null===(t=this.armature)||void 0===t?void 0:t.skeleton){if(this.armature.skeleton.setSkinByName)this.armature.skeleton.setSkinByName(e);else if(this.armature.skeleton.setSkin){const t=(null===(i=null===(s=this.armature.skeleton.data)||void 0===s?void 0:s.findSkin)||void 0===i?void 0:i.call(s,e))||e;this.armature.skeleton.setSkin(t)}null===(o=(n=this.armature.skeleton).setSlotsToSetupPose)||void 0===o||o.call(n)}}play(e,t,s){try{const i=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===s&&(s=0),this.applyTimeScale(),this.armature.state.setAnimation(s,this.animationName,i)):this.waitExecuteInfos.push({playType:!0,name:e,loop:i,track:s})}catch(e){console.log(e)}}stop(e){this.armature?(void 0===e&&(e=0),this.armature.state.setEmptyAnimation(e,0)):this.waitExecuteInfos.push({playType:!1,track:e})}applyTimeScale(){var e;(null===(e=this.armature)||void 0===e?void 0:e.state)&&(this.armature.state.timeScale=this.paused?0:this.timeScale)}addAnimation(e,t,s,i){try{this.armature&&(void 0===i&&(i=0),this.armature.state.addAnimation(i,e,s,t))}catch(e){console.log(e)}}setMix(e,t,s){this.armature&&this.armature.state.data.setMix(e,t,s)}getAnim(e=0){try{if(this.armature)return this.armature.state.tracks[e].animation.name}catch(e){console.log(e)}}setDefaultMix(e){this.armature&&(this.armature.state.data.defaultMix=e)}setAttachment(e,t){this.armature&&this.armature.skeleton.setAttachment(e,t)}getBone(e){if(this.armature)return this.armature.skeleton.findBone(e)}addSlotObject(e,t,s){this.destroied?console.warn("Spine component has been destroyed, cannot addSlotObject"):t&&!t.destroyed?(this._pendingSlotObjects=this._pendingSlotObjects.filter(e=>e.gameObject!==t),this._detachSlotObject(t),this._pendingSlotObjects.push({slot:e,gameObject:t,options:s}),this._flushPendingSlotObjects()):console.warn("Cannot add a destroyed or missing GameObject to a Spine slot")}_doAddSlotObject(e,t,i,n){const o=new s.Container;o.addChild(i),this.armature.addSlotObject(e,o,n),this._slotGameObjects.set(t,{slot:e,wrapper:o}),this._syncTransformTree(t)}_isSlotAvailable(e){var t,s,i,n;if("number"==typeof e){if(!Number.isInteger(e)||e<0)return!1;const i=null===(s=null===(t=this.armature)||void 0===t?void 0:t.skeleton)||void 0===s?void 0:s.slots;return!Array.isArray(i)||e<i.length}if("string"!=typeof e||0===e.length)return!1;const o=null===(n=null===(i=this.armature)||void 0===i?void 0:i.skeleton)||void 0===n?void 0:n.findSlot;return"function"!=typeof o||Boolean(o.call(this.armature.skeleton,e))}_detachSlotObject(e){const t=this._slotGameObjects.get(e);if(t){this.armature&&!this.armature.destroyed&&this.armature.removeSlotObject(t.wrapper);for(const e of[...t.wrapper.children])t.wrapper.removeChild(e);t.wrapper.destroy({children:!1}),this._slotGameObjects.delete(e)}}_syncTransformTree(e){var t;if(this._containerManager&&(this._containerManager.updateTransform({name:e.id,transform:e.transform}),null===(t=e.transform)||void 0===t?void 0:t.children))for(const t of e.transform.children)t.gameObject&&this._syncTransformTree(t.gameObject)}_flushPendingSlotObjects(){if(this.destroied||0===this._pendingSlotObjects.length)return;if(!this.armature||!this._containerManager)return;const e=[],t=this._pendingSlotObjects;this._pendingSlotObjects=[];for(const s of t){if(s.gameObject.destroyed)continue;if(!this._isSlotAvailable(s.slot)){console.warn(`Spine slot "${s.slot}" does not exist; pending slot object was discarded`);continue}const t=this._containerManager.getContainer(s.gameObject.id);if(t)try{this._doAddSlotObject(s.slot,s.gameObject,t,s.options)}catch(e){console.warn(`Failed to add GameObject to Spine slot "${s.slot}"`,e)}else e.push(s)}this._pendingSlotObjects.push(...e)}removeSlotObject(e){this._pendingSlotObjects=this._pendingSlotObjects.filter(t=>t.gameObject!==e),this._detachSlotObject(e)}_destroySlotGameObjects(){const e=new Set([...this._slotGameObjects.keys(),...this._pendingSlotObjects.map(e=>e.gameObject)]);for(const t of e)this._detachSlotObject(t),t.destroyed||t.destroy();this._slotGameObjects.clear(),this._pendingSlotObjects=[]}}a.componentName="Spine",n([i.type("string"),o("design:type",String)],a.prototype,"resource",void 0),n([i.type("number"),o("design:type",Number)],a.prototype,"scale",void 0),n([i.type("string"),o("design:type",String)],a.prototype,"animationName",void 0),n([i.type("boolean"),o("design:type",Boolean)],a.prototype,"autoPlay",void 0),n([i.type("boolean"),o("design:type",Boolean)],a.prototype,"keepResource",void 0),n([i.type("number"),o("design:type",Number)],a.prototype,"timeScale",void 0),n([i.type("string"),o("design:type",String)],a.prototype,"skin",void 0);let c={};function d(e,t,s){return r(this,void 0,void 0,function*(){let i=c[e.name];if(!i)if(e.complete)i=function(e,t,s,i){const n=t.ske,o=t.atlas,r=new i.AtlasAttachmentLoader(o),a=n instanceof Uint8Array?new i.SkeletonBinary(r):new i.SkeletonJson(r);a.scale=s||1;const d={spineData:a.readSkeletonData(n),ref:0,imageSrc:(l=t.image,l?"string"==typeof l?l:l.label||(null===(m=l.source)||void 0===m?void 0:m.label)||(null===(h=null===(u=l.source)||void 0===u?void 0:u.resource)||void 0===h?void 0:h.src)||(null===(p=l.source)||void 0===p?void 0:p._sourceOrigin)||l.src||(null===(y=l.baseTexture)||void 0===y?void 0:y.cacheId)||"":"")};var l,m,u,h,p,y;return c[e]=d,d}(e.name,e.data,t,s);else if(!i)return;return i.ref++,i.spineData})}let l=class extends t.Renderer{constructor(){super(...arguments),this.armatures={},this._spineComponents={}}init({pixiSpine:s}){this.renderSystem=this.game.getSystem(t.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=s,this.game.canvas.addEventListener("webglcontextrestored",()=>{const t=this.game.gameObjects;let s=[];for(let i in this.armatures){const n=+i;for(let i=0;i<t.length;++i){let o=t[i];if(o.id===n){let t=o.getComponent(a);t&&(this.remove({type:e.OBSERVER_TYPE.REMOVE,gameObject:o,component:t,componentName:a.componentName}),s.push({type:e.OBSERVER_TYPE.ADD,gameObject:o,component:t,componentName:a.componentName}));break}}}setTimeout(()=>{s.forEach(e=>{this.add(e)})},1e3)},!1)}update(e){super.update();for(let t in this.armatures){const s=this.armatures[t],i=this._spineComponents[t];!s||s.destroyed||(null==i?void 0:i.destroied)?(this.releaseComponentResource(i),delete this.armatures[t],delete this._spineComponents[t]):s.update(.001*e.deltaTime)}for(let e in this._spineComponents){const t=this._spineComponents[e];t&&!t.destroied?t._flushPendingSlotObjects():(this.releaseComponentResource(t),delete this._spineComponents[e])}}componentChanged(t){return r(this,void 0,void 0,function*(){if("Spine"===t.componentName)if(t.type===e.OBSERVER_TYPE.ADD)this.add(t);else if(t.type===e.OBSERVER_TYPE.CHANGE){if("resource"===t.prop.prop[0])this.change(t)}else t.type===e.OBSERVER_TYPE.REMOVE&&this.remove(t)})}add(t,s){var i,n,o;return r(this,void 0,void 0,function*(){const r=t.component;clearTimeout(r.addHandler);const a=t.gameObject.id,c=this.increaseAsyncId(a),l=yield e.resource.getResource(r.resource);if(!this.validateAsyncId(a,c)||r.destroied||t.gameObject.destroyed)return;const m=yield d(l,r.scale,this.pixiSpine);if(!this.validateAsyncId(a,c)||r.destroied||t.gameObject.destroyed)return;if(!m)return void(r.addHandler=setTimeout(()=>{r.destroied||t.gameObject.destroyed||(void 0===s&&(s=20),--s>0?this.add(t,s):console.log("retry exceed max times",r.resource))},1e3));this.remove(t);const u=null===(n=null===(i=this.renderSystem)||void 0===i?void 0:i.containerManager)||void 0===n?void 0:n.getContainer(t.gameObject.id);if(!u||r.destroied||t.gameObject.destroyed)return;r.lastResource=r.resource;const h=new this.pixiSpine.Spine({skeletonData:m,autoUpdate:!1});if(this.armatures[t.gameObject.id]=h,this._spineComponents[t.gameObject.id]=r,t.gameObject&&t.gameObject.transform){const e=t.gameObject.transform;h.x=e.size.width*e.origin.x,h.y=e.size.height*e.origin.y}u.addChildAt(h,0),h.update(),r._containerManager=null===(o=this.renderSystem)||void 0===o?void 0:o.containerManager,r.armature=h,r.emit("loaded",{resource:r.resource}),h.state.addListener({start:(e,t)=>{r.emit("start",{track:e,name:e.animation.name})},complete:(e,t)=>{r.emit("complete",{track:e,name:e.animation.name})},interrupt:(e,t)=>{r.emit("interrupt",{track:e,name:e.animation.name})},end:(e,t)=>{r.emit("end",{track:e,name:e.animation.name})},event:(e,t)=>{r.emit("event",e,t)}})})}change(e){this.remove(e),this.add(e)}remove(t){var s,i;return r(this,void 0,void 0,function*(){const n=t.gameObject.id;this.increaseAsyncId(n);const o=t.component;clearTimeout(o.addHandler);const r=this.armatures[n],a=null===(i=null===(s=this.renderSystem)||void 0===s?void 0:s.containerManager)||void 0===i?void 0:i.getContainer(n);a&&r&&a.removeChild(r);const c=o.armature;o.armature=null,delete this.armatures[n],delete this._spineComponents[n],c&&(o._destroySlotGameObjects(),c.destroyed||c.destroy({children:!0})),this.releaseComponentResource(o),t.type,e.OBSERVER_TYPE.CHANGE})}onDestroy(){for(const e of Object.keys(this._spineComponents)){const t=this._spineComponents[+e],s=this.armatures[+e];null==t||t._destroySlotGameObjects(),s&&!s.destroyed&&s.destroy({children:!0}),t&&(t.armature=null),this.releaseComponentResource(t)}this.armatures={},this._spineComponents={},this.asyncIdMap={}}releaseComponentResource(t){const s=null==t?void 0:t.lastResource;t&&s&&(t.lastResource="",function(t,s,i=!0){const n=t.name,o=c[n];o&&(o.ref--,o.ref>0||(c[n]===o&&delete c[n],i&&setTimeout(()=>r(this,void 0,void 0,function*(){o.ref<=0&&!c[n]&&e.resource.destroy(n)}),100)))}({name:s},0,!t.keepResource))}};l.systemName="SpineSystem",l=n([e.decorators.componentObserver({Spine:["resource"]})],l);var m=l;e.resource.registerResourceType("SPINE"),exports.Spine=a,exports.SpineSystem=m;
|
package/dist/spine-base.d.ts
CHANGED
|
@@ -9,6 +9,14 @@ import { RendererManager } from '@eva/plugin-renderer';
|
|
|
9
9
|
import { RendererSystem } from '@eva/plugin-renderer';
|
|
10
10
|
import { UpdateParams } from '@eva/eva.js';
|
|
11
11
|
|
|
12
|
+
declare interface PendingSlotObject {
|
|
13
|
+
slot: number | string;
|
|
14
|
+
gameObject: GameObject;
|
|
15
|
+
options?: {
|
|
16
|
+
followAttachmentTimeline?: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
/**
|
|
13
21
|
* Spine 骨骼动画组件
|
|
14
22
|
*
|
|
@@ -90,25 +98,15 @@ export declare class Spine extends Component<SpineParams> {
|
|
|
90
98
|
private _armature;
|
|
91
99
|
/** 容器管理器引用(由 SpineSystem 设置) */
|
|
92
100
|
_containerManager: any;
|
|
93
|
-
/** 挂载到插槽的 GameObject
|
|
101
|
+
/** 挂载到插槽的 GameObject 及对应 slot/wrapper 映射 */
|
|
94
102
|
private _slotGameObjects;
|
|
95
103
|
/** 等待容器就绪的 slot 挂载请求 */
|
|
96
|
-
_pendingSlotObjects:
|
|
97
|
-
slot: number | string;
|
|
98
|
-
gameObject: GameObject;
|
|
99
|
-
options?: {
|
|
100
|
-
followAttachmentTimeline?: boolean;
|
|
101
|
-
};
|
|
102
|
-
}[];
|
|
104
|
+
_pendingSlotObjects: PendingSlotObject[];
|
|
103
105
|
/** 等待执行的动画操作队列 */
|
|
104
106
|
private waitExecuteInfos;
|
|
105
107
|
private listenerBound;
|
|
106
108
|
private paused;
|
|
107
109
|
constructor(params?: SpineParams);
|
|
108
|
-
/**
|
|
109
|
-
* 设置骨架实例
|
|
110
|
-
* 当骨架加载完成后自动执行等待队列中的动画操作
|
|
111
|
-
*/
|
|
112
110
|
set armature(val: any);
|
|
113
111
|
/** 获取骨架实例 */
|
|
114
112
|
get armature(): any;
|
|
@@ -222,6 +220,8 @@ export declare class Spine extends Component<SpineParams> {
|
|
|
222
220
|
followAttachmentTimeline?: boolean;
|
|
223
221
|
}): void;
|
|
224
222
|
private _doAddSlotObject;
|
|
223
|
+
private _isSlotAvailable;
|
|
224
|
+
private _detachSlotObject;
|
|
225
225
|
/**
|
|
226
226
|
* 递归同步 gameObject 及其子树的 transform 到对应的渲染容器
|
|
227
227
|
*/
|
|
@@ -300,6 +300,8 @@ export declare class SpineSystem extends Renderer {
|
|
|
300
300
|
add(changed: ComponentChanged, count?: number): Promise<void>;
|
|
301
301
|
change(changed: ComponentChanged): void;
|
|
302
302
|
remove(changed: ComponentChanged): Promise<void>;
|
|
303
|
+
onDestroy(): void;
|
|
304
|
+
private releaseComponentResource;
|
|
303
305
|
}
|
|
304
306
|
|
|
305
307
|
export { }
|
package/dist/spine-base.esm.js
CHANGED
|
@@ -115,7 +115,7 @@ class Spine extends Component {
|
|
|
115
115
|
this.timeScale = 1;
|
|
116
116
|
/** 当前皮肤名称 */
|
|
117
117
|
this.skin = '';
|
|
118
|
-
/** 挂载到插槽的 GameObject
|
|
118
|
+
/** 挂载到插槽的 GameObject 及对应 slot/wrapper 映射 */
|
|
119
119
|
this._slotGameObjects = new Map();
|
|
120
120
|
/** 等待容器就绪的 slot 挂载请求 */
|
|
121
121
|
this._pendingSlotObjects = [];
|
|
@@ -125,10 +125,7 @@ class Spine extends Component {
|
|
|
125
125
|
this.paused = false;
|
|
126
126
|
this.init(params);
|
|
127
127
|
}
|
|
128
|
-
|
|
129
|
-
* 设置骨架实例
|
|
130
|
-
* 当骨架加载完成后自动执行等待队列中的动画操作
|
|
131
|
-
*/
|
|
128
|
+
// 设置骨架实例;骨架加载完成后自动执行等待队列中的动画操作。
|
|
132
129
|
set armature(val) {
|
|
133
130
|
this._armature = val;
|
|
134
131
|
if (!val)
|
|
@@ -149,6 +146,7 @@ class Spine extends Component {
|
|
|
149
146
|
}
|
|
150
147
|
}
|
|
151
148
|
this.waitExecuteInfos = [];
|
|
149
|
+
this._flushPendingSlotObjects();
|
|
152
150
|
}
|
|
153
151
|
/** 获取骨架实例 */
|
|
154
152
|
get armature() {
|
|
@@ -190,8 +188,8 @@ class Spine extends Component {
|
|
|
190
188
|
}
|
|
191
189
|
destroy() {
|
|
192
190
|
this.onDestroy();
|
|
191
|
+
this._destroySlotGameObjects();
|
|
193
192
|
if (this.armature && !this.armature.destroyed) {
|
|
194
|
-
this._destroySlotGameObjects();
|
|
195
193
|
this.armature.destroy({ children: true });
|
|
196
194
|
}
|
|
197
195
|
this.armature = null;
|
|
@@ -395,21 +393,19 @@ class Spine extends Component {
|
|
|
395
393
|
* @param options.followAttachmentTimeline - 是否跟随插槽的附件时间线
|
|
396
394
|
*/
|
|
397
395
|
addSlotObject(slot, gameObject, options) {
|
|
398
|
-
if (
|
|
399
|
-
console.warn('Spine
|
|
396
|
+
if (this.destroied) {
|
|
397
|
+
console.warn('Spine component has been destroyed, cannot addSlotObject');
|
|
400
398
|
return;
|
|
401
399
|
}
|
|
402
|
-
if (!
|
|
403
|
-
console.warn('
|
|
400
|
+
if (!gameObject || gameObject.destroyed) {
|
|
401
|
+
console.warn('Cannot add a destroyed or missing GameObject to a Spine slot');
|
|
404
402
|
return;
|
|
405
403
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
this._doAddSlotObject(slot, gameObject, container, options);
|
|
404
|
+
// 同一 GameObject 只保留最后一次挂载意图,避免依赖分阶段就绪时重复挂载。
|
|
405
|
+
this._pendingSlotObjects = this._pendingSlotObjects.filter(pending => pending.gameObject !== gameObject);
|
|
406
|
+
this._detachSlotObject(gameObject);
|
|
407
|
+
this._pendingSlotObjects.push({ slot, gameObject, options });
|
|
408
|
+
this._flushPendingSlotObjects();
|
|
413
409
|
}
|
|
414
410
|
_doAddSlotObject(slot, gameObject, container, options) {
|
|
415
411
|
// 创建 wrapper 容器:Spine 骨骼矩阵作用在 wrapper 上,
|
|
@@ -422,6 +418,32 @@ class Spine extends Component {
|
|
|
422
418
|
// 手动同步 gameObject 及其子树的 transform 到 container
|
|
423
419
|
this._syncTransformTree(gameObject);
|
|
424
420
|
}
|
|
421
|
+
_isSlotAvailable(slot) {
|
|
422
|
+
var _a, _b, _c, _d;
|
|
423
|
+
if (typeof slot === 'number') {
|
|
424
|
+
if (!Number.isInteger(slot) || slot < 0)
|
|
425
|
+
return false;
|
|
426
|
+
const slots = (_b = (_a = this.armature) === null || _a === void 0 ? void 0 : _a.skeleton) === null || _b === void 0 ? void 0 : _b.slots;
|
|
427
|
+
return !Array.isArray(slots) || slot < slots.length;
|
|
428
|
+
}
|
|
429
|
+
if (typeof slot !== 'string' || slot.length === 0)
|
|
430
|
+
return false;
|
|
431
|
+
const findSlot = (_d = (_c = this.armature) === null || _c === void 0 ? void 0 : _c.skeleton) === null || _d === void 0 ? void 0 : _d.findSlot;
|
|
432
|
+
return typeof findSlot !== 'function' || Boolean(findSlot.call(this.armature.skeleton, slot));
|
|
433
|
+
}
|
|
434
|
+
_detachSlotObject(gameObject) {
|
|
435
|
+
const entry = this._slotGameObjects.get(gameObject);
|
|
436
|
+
if (!entry)
|
|
437
|
+
return;
|
|
438
|
+
if (this.armature && !this.armature.destroyed) {
|
|
439
|
+
this.armature.removeSlotObject(entry.wrapper);
|
|
440
|
+
}
|
|
441
|
+
for (const child of [...entry.wrapper.children]) {
|
|
442
|
+
entry.wrapper.removeChild(child);
|
|
443
|
+
}
|
|
444
|
+
entry.wrapper.destroy({ children: false });
|
|
445
|
+
this._slotGameObjects.delete(gameObject);
|
|
446
|
+
}
|
|
425
447
|
/**
|
|
426
448
|
* 递归同步 gameObject 及其子树的 transform 到对应的渲染容器
|
|
427
449
|
*/
|
|
@@ -445,21 +467,34 @@ class Spine extends Component {
|
|
|
445
467
|
* 处理等待容器就绪的 slot 挂载请求(由 SpineSystem 每帧调用)
|
|
446
468
|
*/
|
|
447
469
|
_flushPendingSlotObjects() {
|
|
448
|
-
if (this._pendingSlotObjects.length === 0)
|
|
470
|
+
if (this.destroied || this._pendingSlotObjects.length === 0)
|
|
449
471
|
return;
|
|
450
472
|
if (!this.armature || !this._containerManager)
|
|
451
473
|
return;
|
|
452
474
|
const still = [];
|
|
453
|
-
|
|
475
|
+
const pendingSlotObjects = this._pendingSlotObjects;
|
|
476
|
+
this._pendingSlotObjects = [];
|
|
477
|
+
for (const pending of pendingSlotObjects) {
|
|
478
|
+
if (pending.gameObject.destroyed)
|
|
479
|
+
continue;
|
|
480
|
+
if (!this._isSlotAvailable(pending.slot)) {
|
|
481
|
+
console.warn(`Spine slot "${pending.slot}" does not exist; pending slot object was discarded`);
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
454
484
|
const container = this._containerManager.getContainer(pending.gameObject.id);
|
|
455
485
|
if (container) {
|
|
456
|
-
|
|
486
|
+
try {
|
|
487
|
+
this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
console.warn(`Failed to add GameObject to Spine slot "${pending.slot}"`, error);
|
|
491
|
+
}
|
|
457
492
|
}
|
|
458
493
|
else {
|
|
459
494
|
still.push(pending);
|
|
460
495
|
}
|
|
461
496
|
}
|
|
462
|
-
this._pendingSlotObjects
|
|
497
|
+
this._pendingSlotObjects.push(...still);
|
|
463
498
|
}
|
|
464
499
|
/**
|
|
465
500
|
* 从插槽上移除挂载的 GameObject
|
|
@@ -469,24 +504,19 @@ class Spine extends Component {
|
|
|
469
504
|
removeSlotObject(gameObject) {
|
|
470
505
|
// 从 pending 队列中移除
|
|
471
506
|
this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
|
|
472
|
-
|
|
473
|
-
if (entry && this.armature) {
|
|
474
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
475
|
-
entry.wrapper.destroy({ children: false });
|
|
476
|
-
}
|
|
477
|
-
this._slotGameObjects.delete(gameObject);
|
|
507
|
+
this._detachSlotObject(gameObject);
|
|
478
508
|
}
|
|
479
509
|
/**
|
|
480
510
|
* 销毁所有挂载到插槽的 GameObject(内部使用)
|
|
481
511
|
*/
|
|
482
512
|
_destroySlotGameObjects() {
|
|
483
|
-
|
|
513
|
+
const gameObjects = new Set([
|
|
514
|
+
...this._slotGameObjects.keys(),
|
|
515
|
+
...this._pendingSlotObjects.map(pending => pending.gameObject),
|
|
516
|
+
]);
|
|
517
|
+
for (const gameObject of gameObjects) {
|
|
518
|
+
this._detachSlotObject(gameObject);
|
|
484
519
|
if (!gameObject.destroyed) {
|
|
485
|
-
// 先从 spine 插槽移除 wrapper,避免 destroy 时重复操作
|
|
486
|
-
if (this.armature) {
|
|
487
|
-
this.armature.removeSlotObject(entry.wrapper);
|
|
488
|
-
}
|
|
489
|
-
entry.wrapper.destroy({ children: false });
|
|
490
520
|
gameObject.destroy();
|
|
491
521
|
}
|
|
492
522
|
}
|
|
@@ -570,17 +600,31 @@ function getSpineData(res, scale, pixiSpine) {
|
|
|
570
600
|
return data.spineData;
|
|
571
601
|
});
|
|
572
602
|
}
|
|
573
|
-
function releaseSpineData(res, _imageSrc) {
|
|
603
|
+
function releaseSpineData(res, _imageSrc, destroyResource = true) {
|
|
574
604
|
const resourceName = res.name;
|
|
575
605
|
const data = dataMap[resourceName];
|
|
576
606
|
if (!data) {
|
|
577
607
|
return;
|
|
578
608
|
}
|
|
579
609
|
data.ref--;
|
|
610
|
+
if (data.ref > 0) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
// Parsed skeleton data owns attachment objects that point at Pixi textures.
|
|
614
|
+
// Armature teardown can invalidate those objects even when the raw resource
|
|
615
|
+
// is intentionally kept. Remove this generation immediately so the next
|
|
616
|
+
// EvaApp reparses the still-loaded atlas instead of rendering stale sources.
|
|
617
|
+
if (dataMap[resourceName] === data) {
|
|
618
|
+
delete dataMap[resourceName];
|
|
619
|
+
}
|
|
620
|
+
if (!destroyResource) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
580
623
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
581
|
-
|
|
624
|
+
// A newer EvaApp may have rebuilt the same resource name while this delayed
|
|
625
|
+
// release was pending. Never unload the replacement generation's assets.
|
|
626
|
+
if (data.ref <= 0 && !dataMap[resourceName]) {
|
|
582
627
|
resource.destroy(resourceName);
|
|
583
|
-
delete dataMap[resourceName];
|
|
584
628
|
}
|
|
585
629
|
}), 100);
|
|
586
630
|
}
|
|
@@ -663,6 +707,7 @@ let SpineSystem = class SpineSystem extends Renderer {
|
|
|
663
707
|
const armature = this.armatures[key];
|
|
664
708
|
const component = this._spineComponents[key];
|
|
665
709
|
if (!armature || armature.destroyed || (component === null || component === void 0 ? void 0 : component.destroied)) {
|
|
710
|
+
this.releaseComponentResource(component);
|
|
666
711
|
delete this.armatures[key];
|
|
667
712
|
delete this._spineComponents[key];
|
|
668
713
|
continue;
|
|
@@ -675,6 +720,7 @@ let SpineSystem = class SpineSystem extends Renderer {
|
|
|
675
720
|
for (let key in this._spineComponents) {
|
|
676
721
|
const component = this._spineComponents[key];
|
|
677
722
|
if (!component || component.destroied) {
|
|
723
|
+
this.releaseComponentResource(component);
|
|
678
724
|
delete this._spineComponents[key];
|
|
679
725
|
continue;
|
|
680
726
|
}
|
|
@@ -786,7 +832,7 @@ let SpineSystem = class SpineSystem extends Renderer {
|
|
|
786
832
|
this.add(changed);
|
|
787
833
|
}
|
|
788
834
|
remove(changed) {
|
|
789
|
-
var _a, _b
|
|
835
|
+
var _a, _b;
|
|
790
836
|
return __awaiter(this, void 0, void 0, function* () {
|
|
791
837
|
const gameObjectId = changed.gameObject.id;
|
|
792
838
|
this.increaseAsyncId(gameObjectId);
|
|
@@ -807,20 +853,36 @@ let SpineSystem = class SpineSystem extends Renderer {
|
|
|
807
853
|
if (!componentArmature.destroyed) {
|
|
808
854
|
componentArmature.destroy({ children: true });
|
|
809
855
|
}
|
|
810
|
-
if (!component.keepResource && component.lastResource) {
|
|
811
|
-
try {
|
|
812
|
-
const res = yield resource.getResource(component.lastResource);
|
|
813
|
-
const imageSrc = ((_d = (_c = res.data) === null || _c === void 0 ? void 0 : _c.image) === null || _d === void 0 ? void 0 : _d.src) || ((_f = (_e = res.data) === null || _e === void 0 ? void 0 : _e.image) === null || _f === void 0 ? void 0 : _f.label);
|
|
814
|
-
releaseSpineData(res, imageSrc);
|
|
815
|
-
}
|
|
816
|
-
catch (error) {
|
|
817
|
-
console.warn('Failed to release Spine resource', component.lastResource, error);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
856
|
}
|
|
857
|
+
this.releaseComponentResource(component);
|
|
821
858
|
if (changed.type === OBSERVER_TYPE.CHANGE) ;
|
|
822
859
|
});
|
|
823
860
|
}
|
|
861
|
+
onDestroy() {
|
|
862
|
+
for (const key of Object.keys(this._spineComponents)) {
|
|
863
|
+
const component = this._spineComponents[+key];
|
|
864
|
+
const armature = this.armatures[+key];
|
|
865
|
+
component === null || component === void 0 ? void 0 : component._destroySlotGameObjects();
|
|
866
|
+
if (armature && !armature.destroyed) {
|
|
867
|
+
armature.destroy({ children: true });
|
|
868
|
+
}
|
|
869
|
+
if (component) {
|
|
870
|
+
component.armature = null;
|
|
871
|
+
}
|
|
872
|
+
this.releaseComponentResource(component);
|
|
873
|
+
}
|
|
874
|
+
this.armatures = {};
|
|
875
|
+
this._spineComponents = {};
|
|
876
|
+
this.asyncIdMap = {};
|
|
877
|
+
}
|
|
878
|
+
releaseComponentResource(component) {
|
|
879
|
+
const resourceName = component === null || component === void 0 ? void 0 : component.lastResource;
|
|
880
|
+
if (!component || !resourceName) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
component.lastResource = '';
|
|
884
|
+
releaseSpineData({ name: resourceName }, '', !component.keepResource);
|
|
885
|
+
}
|
|
824
886
|
};
|
|
825
887
|
/** 系统名称 */
|
|
826
888
|
SpineSystem.systemName = 'SpineSystem';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eva/spine-base",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.12",
|
|
4
4
|
"description": "@eva/spine-base",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/spine-base.esm.js",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"homepage": "https://eva.js.org",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@eva/eva.js": "2.1.0-beta.
|
|
22
|
-
"@eva/plugin-renderer": "2.1.0-beta.
|
|
21
|
+
"@eva/eva.js": "2.1.0-beta.12",
|
|
22
|
+
"@eva/plugin-renderer": "2.1.0-beta.12",
|
|
23
23
|
"@eva/inspector-decorator": "^2.0.0-beta.0",
|
|
24
24
|
"pixi.js": "^8.17.0"
|
|
25
25
|
}
|