@eva/spine-base 2.0.1-beta.39 → 2.0.1-beta.40

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.
@@ -1,7 +1,7 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
2
  globalThis.EVA = globalThis.EVA || {};
3
3
  globalThis.EVA.plugin = globalThis.EVA.plugin || {};
4
- var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
4
+ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer, pixi_js) {
5
5
  'use strict';
6
6
  function __decorate(decorators, target, key, desc) {
7
7
  var c = arguments.length,
@@ -63,6 +63,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
63
63
  this.autoPlay = true;
64
64
  this.keepResource = false;
65
65
  this._slotGameObjects = new Map();
66
+ this._pendingSlotObjects = [];
66
67
  this.waitExecuteInfos = [];
67
68
  }
68
69
  set armature(val) {
@@ -183,33 +184,79 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
183
184
  }
184
185
  const container = this._containerManager.getContainer(gameObject.id);
185
186
  if (!container) {
186
- console.warn('GameObject does not have a render container');
187
+ this._pendingSlotObjects.push({
188
+ slot,
189
+ gameObject,
190
+ options
191
+ });
187
192
  return;
188
193
  }
189
- this.armature.addSlotObject(slot, container, options);
190
- this._slotGameObjects.set(gameObject, slot);
194
+ this._doAddSlotObject(slot, gameObject, container, options);
191
195
  }
192
- removeSlotObject(gameObject) {
193
- if (!this.armature) return;
196
+ _doAddSlotObject(slot, gameObject, container, options) {
197
+ const wrapper = new pixi_js.Container();
198
+ wrapper.addChild(container);
199
+ this.armature.addSlotObject(slot, wrapper, options);
200
+ this._slotGameObjects.set(gameObject, {
201
+ slot,
202
+ wrapper
203
+ });
204
+ this._syncTransformTree(gameObject);
205
+ }
206
+ _syncTransformTree(gameObject) {
207
+ var _a;
194
208
  if (!this._containerManager) return;
195
- const container = this._containerManager.getContainer(gameObject.id);
196
- if (container) {
197
- this.armature.removeSlotObject(container);
209
+ this._containerManager.updateTransform({
210
+ name: gameObject.id,
211
+ transform: gameObject.transform
212
+ });
213
+ if ((_a = gameObject.transform) === null || _a === void 0 ? void 0 : _a.children) {
214
+ for (const childTransform of gameObject.transform.children) {
215
+ if (childTransform.gameObject) {
216
+ this._syncTransformTree(childTransform.gameObject);
217
+ }
218
+ }
219
+ }
220
+ }
221
+ _flushPendingSlotObjects() {
222
+ if (this._pendingSlotObjects.length === 0) return;
223
+ if (!this.armature || !this._containerManager) return;
224
+ const still = [];
225
+ for (const pending of this._pendingSlotObjects) {
226
+ const container = this._containerManager.getContainer(pending.gameObject.id);
227
+ if (container) {
228
+ this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
229
+ } else {
230
+ still.push(pending);
231
+ }
232
+ }
233
+ this._pendingSlotObjects = still;
234
+ }
235
+ removeSlotObject(gameObject) {
236
+ this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
237
+ const entry = this._slotGameObjects.get(gameObject);
238
+ if (entry && this.armature) {
239
+ this.armature.removeSlotObject(entry.wrapper);
240
+ entry.wrapper.destroy({
241
+ children: false
242
+ });
198
243
  }
199
244
  this._slotGameObjects.delete(gameObject);
200
245
  }
201
246
  _destroySlotGameObjects() {
202
- var _a;
203
- for (const [gameObject] of this._slotGameObjects) {
247
+ for (const [gameObject, entry] of this._slotGameObjects) {
204
248
  if (!gameObject.destroyed) {
205
- const container = (_a = this._containerManager) === null || _a === void 0 ? void 0 : _a.getContainer(gameObject.id);
206
- if (container && this.armature) {
207
- this.armature.removeSlotObject(container);
249
+ if (this.armature) {
250
+ this.armature.removeSlotObject(entry.wrapper);
208
251
  }
252
+ entry.wrapper.destroy({
253
+ children: false
254
+ });
209
255
  gameObject.destroy();
210
256
  }
211
257
  }
212
258
  this._slotGameObjects.clear();
259
+ this._pendingSlotObjects = [];
213
260
  }
214
261
  }
215
262
  Spine.componentName = 'Spine';
@@ -267,6 +314,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
267
314
  constructor() {
268
315
  super(...arguments);
269
316
  this.armatures = {};
317
+ this._spineComponents = {};
270
318
  }
271
319
  init({
272
320
  pixiSpine
@@ -312,6 +360,9 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
312
360
  for (let key in this.armatures) {
313
361
  this.armatures[key].update(e.deltaTime * 0.001);
314
362
  }
363
+ for (let key in this._spineComponents) {
364
+ this._spineComponents[key]._flushPendingSlotObjects();
365
+ }
315
366
  super.update();
316
367
  }
317
368
  componentChanged(changed) {
@@ -369,6 +420,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
369
420
  autoUpdate: false
370
421
  });
371
422
  this.armatures[changed.gameObject.id] = armature;
423
+ this._spineComponents[changed.gameObject.id] = component;
372
424
  if (changed.gameObject && changed.gameObject.transform) {
373
425
  const tran = changed.gameObject.transform;
374
426
  armature.x = tran.size.width * tran.origin.x;
@@ -440,6 +492,7 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
440
492
  }
441
493
  component.armature = null;
442
494
  delete this.armatures[changed.gameObject.id];
495
+ delete this._spineComponents[changed.gameObject.id];
443
496
  if (changed.type === eva_js.OBSERVER_TYPE.CHANGE) ;
444
497
  });
445
498
  }
@@ -456,5 +509,5 @@ var _EVA_IIFE_spineBase = function (exports, eva_js, pluginRenderer) {
456
509
  value: true
457
510
  });
458
511
  return exports;
459
- }({}, EVA, EVA.plugin.renderer);
512
+ }({}, EVA, EVA.plugin.renderer, PIXI);
460
513
  globalThis.EVA.plugin.spineBase = globalThis.EVA.plugin.spineBase || _EVA_IIFE_spineBase;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var eva_js = require('@eva/eva.js');
6
6
  var pluginRenderer = require('@eva/plugin-renderer');
7
+ var pixi_js = require('pixi.js');
7
8
  var inspectorDecorator = require('@eva/inspector-decorator');
8
9
 
9
10
  /*! *****************************************************************************
@@ -104,8 +105,10 @@ class Spine extends eva_js.Component {
104
105
  this.autoPlay = true;
105
106
  /** 是否保留资源(销毁时不释放) */
106
107
  this.keepResource = false;
107
- /** 挂载到插槽的 GameObject 映射(GameObject -> slot 标识) */
108
+ /** 挂载到插槽的 GameObject 映射(GameObject -> { slot, wrapper }) */
108
109
  this._slotGameObjects = new Map();
110
+ /** 等待容器就绪的 slot 挂载请求 */
111
+ this._pendingSlotObjects = [];
109
112
  /** 等待执行的动画操作队列 */
110
113
  this.waitExecuteInfos = [];
111
114
  }
@@ -332,11 +335,61 @@ class Spine extends eva_js.Component {
332
335
  }
333
336
  const container = this._containerManager.getContainer(gameObject.id);
334
337
  if (!container) {
335
- console.warn('GameObject does not have a render container');
338
+ // 容器尚未就绪,加入 pending 队列,等待下一帧自动处理
339
+ this._pendingSlotObjects.push({ slot, gameObject, options });
336
340
  return;
337
341
  }
338
- this.armature.addSlotObject(slot, container, options);
339
- this._slotGameObjects.set(gameObject, slot);
342
+ this._doAddSlotObject(slot, gameObject, container, options);
343
+ }
344
+ _doAddSlotObject(slot, gameObject, container, options) {
345
+ // 创建 wrapper 容器:Spine 骨骼矩阵作用在 wrapper 上,
346
+ // gameObject 的 container 作为子节点,其 transform 作为相对 slot 的局部偏移
347
+ const wrapper = new pixi_js.Container();
348
+ wrapper.addChild(container);
349
+ this.armature.addSlotObject(slot, wrapper, options);
350
+ this._slotGameObjects.set(gameObject, { slot, wrapper });
351
+ // slot object 可能不在 game.gameObjects 中,RendererSystem 不会自动同步 transform
352
+ // 手动同步 gameObject 及其子树的 transform 到 container
353
+ this._syncTransformTree(gameObject);
354
+ }
355
+ /**
356
+ * 递归同步 gameObject 及其子树的 transform 到对应的渲染容器
357
+ */
358
+ _syncTransformTree(gameObject) {
359
+ var _a;
360
+ if (!this._containerManager)
361
+ return;
362
+ this._containerManager.updateTransform({
363
+ name: gameObject.id,
364
+ transform: gameObject.transform,
365
+ });
366
+ if ((_a = gameObject.transform) === null || _a === void 0 ? void 0 : _a.children) {
367
+ for (const childTransform of gameObject.transform.children) {
368
+ if (childTransform.gameObject) {
369
+ this._syncTransformTree(childTransform.gameObject);
370
+ }
371
+ }
372
+ }
373
+ }
374
+ /**
375
+ * 处理等待容器就绪的 slot 挂载请求(由 SpineSystem 每帧调用)
376
+ */
377
+ _flushPendingSlotObjects() {
378
+ if (this._pendingSlotObjects.length === 0)
379
+ return;
380
+ if (!this.armature || !this._containerManager)
381
+ return;
382
+ const still = [];
383
+ for (const pending of this._pendingSlotObjects) {
384
+ const container = this._containerManager.getContainer(pending.gameObject.id);
385
+ if (container) {
386
+ this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
387
+ }
388
+ else {
389
+ still.push(pending);
390
+ }
391
+ }
392
+ this._pendingSlotObjects = still;
340
393
  }
341
394
  /**
342
395
  * 从插槽上移除挂载的 GameObject
@@ -344,13 +397,12 @@ class Spine extends eva_js.Component {
344
397
  * @param gameObject - 要移除的 GameObject
345
398
  */
346
399
  removeSlotObject(gameObject) {
347
- if (!this.armature)
348
- return;
349
- if (!this._containerManager)
350
- return;
351
- const container = this._containerManager.getContainer(gameObject.id);
352
- if (container) {
353
- this.armature.removeSlotObject(container);
400
+ // 从 pending 队列中移除
401
+ this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
402
+ const entry = this._slotGameObjects.get(gameObject);
403
+ if (entry && this.armature) {
404
+ this.armature.removeSlotObject(entry.wrapper);
405
+ entry.wrapper.destroy({ children: false });
354
406
  }
355
407
  this._slotGameObjects.delete(gameObject);
356
408
  }
@@ -358,18 +410,18 @@ class Spine extends eva_js.Component {
358
410
  * 销毁所有挂载到插槽的 GameObject(内部使用)
359
411
  */
360
412
  _destroySlotGameObjects() {
361
- var _a;
362
- for (const [gameObject] of this._slotGameObjects) {
413
+ for (const [gameObject, entry] of this._slotGameObjects) {
363
414
  if (!gameObject.destroyed) {
364
- // 先从 spine 插槽移除,避免 destroy 时重复操作
365
- const container = (_a = this._containerManager) === null || _a === void 0 ? void 0 : _a.getContainer(gameObject.id);
366
- if (container && this.armature) {
367
- this.armature.removeSlotObject(container);
415
+ // 先从 spine 插槽移除 wrapper,避免 destroy 时重复操作
416
+ if (this.armature) {
417
+ this.armature.removeSlotObject(entry.wrapper);
368
418
  }
419
+ entry.wrapper.destroy({ children: false });
369
420
  gameObject.destroy();
370
421
  }
371
422
  }
372
423
  this._slotGameObjects.clear();
424
+ this._pendingSlotObjects = [];
373
425
  }
374
426
  }
375
427
  /** 组件名称 */
@@ -454,6 +506,8 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
454
506
  super(...arguments);
455
507
  /** 骨架实例映射表(游戏对象 ID -> 骨架容器) */
456
508
  this.armatures = {};
509
+ /** Spine 组件实例映射(游戏对象 ID -> Spine 组件) */
510
+ this._spineComponents = {};
457
511
  }
458
512
  /**
459
513
  * 初始化系统
@@ -510,6 +564,10 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
510
564
  // @ts-ignore
511
565
  this.armatures[key].update(e.deltaTime * 0.001);
512
566
  }
567
+ // 处理等待容器就绪的 slot 挂载请求
568
+ for (let key in this._spineComponents) {
569
+ this._spineComponents[key]._flushPendingSlotObjects();
570
+ }
513
571
  super.update();
514
572
  }
515
573
  componentChanged(changed) {
@@ -575,6 +633,7 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
575
633
  autoUpdate: false,
576
634
  });
577
635
  this.armatures[changed.gameObject.id] = armature;
636
+ this._spineComponents[changed.gameObject.id] = component;
578
637
  if (changed.gameObject && changed.gameObject.transform) {
579
638
  const tran = changed.gameObject.transform;
580
639
  armature.x = tran.size.width * tran.origin.x;
@@ -638,6 +697,7 @@ let SpineSystem = class SpineSystem extends pluginRenderer.Renderer {
638
697
  }
639
698
  component.armature = null;
640
699
  delete this.armatures[changed.gameObject.id];
700
+ delete this._spineComponents[changed.gameObject.id];
641
701
  if (changed.type === eva_js.OBSERVER_TYPE.CHANGE) ;
642
702
  });
643
703
  }
@@ -1,5 +1,6 @@
1
1
  import { Component, resource, OBSERVER_TYPE, decorators } from '@eva/eva.js';
2
2
  import { Renderer, RendererSystem } from '@eva/plugin-renderer';
3
+ import { Container } from 'pixi.js';
3
4
  import { type } from '@eva/inspector-decorator';
4
5
 
5
6
  /*! *****************************************************************************
@@ -100,8 +101,10 @@ class Spine extends Component {
100
101
  this.autoPlay = true;
101
102
  /** 是否保留资源(销毁时不释放) */
102
103
  this.keepResource = false;
103
- /** 挂载到插槽的 GameObject 映射(GameObject -> slot 标识) */
104
+ /** 挂载到插槽的 GameObject 映射(GameObject -> { slot, wrapper }) */
104
105
  this._slotGameObjects = new Map();
106
+ /** 等待容器就绪的 slot 挂载请求 */
107
+ this._pendingSlotObjects = [];
105
108
  /** 等待执行的动画操作队列 */
106
109
  this.waitExecuteInfos = [];
107
110
  }
@@ -328,11 +331,61 @@ class Spine extends Component {
328
331
  }
329
332
  const container = this._containerManager.getContainer(gameObject.id);
330
333
  if (!container) {
331
- console.warn('GameObject does not have a render container');
334
+ // 容器尚未就绪,加入 pending 队列,等待下一帧自动处理
335
+ this._pendingSlotObjects.push({ slot, gameObject, options });
332
336
  return;
333
337
  }
334
- this.armature.addSlotObject(slot, container, options);
335
- this._slotGameObjects.set(gameObject, slot);
338
+ this._doAddSlotObject(slot, gameObject, container, options);
339
+ }
340
+ _doAddSlotObject(slot, gameObject, container, options) {
341
+ // 创建 wrapper 容器:Spine 骨骼矩阵作用在 wrapper 上,
342
+ // gameObject 的 container 作为子节点,其 transform 作为相对 slot 的局部偏移
343
+ const wrapper = new Container();
344
+ wrapper.addChild(container);
345
+ this.armature.addSlotObject(slot, wrapper, options);
346
+ this._slotGameObjects.set(gameObject, { slot, wrapper });
347
+ // slot object 可能不在 game.gameObjects 中,RendererSystem 不会自动同步 transform
348
+ // 手动同步 gameObject 及其子树的 transform 到 container
349
+ this._syncTransformTree(gameObject);
350
+ }
351
+ /**
352
+ * 递归同步 gameObject 及其子树的 transform 到对应的渲染容器
353
+ */
354
+ _syncTransformTree(gameObject) {
355
+ var _a;
356
+ if (!this._containerManager)
357
+ return;
358
+ this._containerManager.updateTransform({
359
+ name: gameObject.id,
360
+ transform: gameObject.transform,
361
+ });
362
+ if ((_a = gameObject.transform) === null || _a === void 0 ? void 0 : _a.children) {
363
+ for (const childTransform of gameObject.transform.children) {
364
+ if (childTransform.gameObject) {
365
+ this._syncTransformTree(childTransform.gameObject);
366
+ }
367
+ }
368
+ }
369
+ }
370
+ /**
371
+ * 处理等待容器就绪的 slot 挂载请求(由 SpineSystem 每帧调用)
372
+ */
373
+ _flushPendingSlotObjects() {
374
+ if (this._pendingSlotObjects.length === 0)
375
+ return;
376
+ if (!this.armature || !this._containerManager)
377
+ return;
378
+ const still = [];
379
+ for (const pending of this._pendingSlotObjects) {
380
+ const container = this._containerManager.getContainer(pending.gameObject.id);
381
+ if (container) {
382
+ this._doAddSlotObject(pending.slot, pending.gameObject, container, pending.options);
383
+ }
384
+ else {
385
+ still.push(pending);
386
+ }
387
+ }
388
+ this._pendingSlotObjects = still;
336
389
  }
337
390
  /**
338
391
  * 从插槽上移除挂载的 GameObject
@@ -340,13 +393,12 @@ class Spine extends Component {
340
393
  * @param gameObject - 要移除的 GameObject
341
394
  */
342
395
  removeSlotObject(gameObject) {
343
- if (!this.armature)
344
- return;
345
- if (!this._containerManager)
346
- return;
347
- const container = this._containerManager.getContainer(gameObject.id);
348
- if (container) {
349
- this.armature.removeSlotObject(container);
396
+ // 从 pending 队列中移除
397
+ this._pendingSlotObjects = this._pendingSlotObjects.filter(p => p.gameObject !== gameObject);
398
+ const entry = this._slotGameObjects.get(gameObject);
399
+ if (entry && this.armature) {
400
+ this.armature.removeSlotObject(entry.wrapper);
401
+ entry.wrapper.destroy({ children: false });
350
402
  }
351
403
  this._slotGameObjects.delete(gameObject);
352
404
  }
@@ -354,18 +406,18 @@ class Spine extends Component {
354
406
  * 销毁所有挂载到插槽的 GameObject(内部使用)
355
407
  */
356
408
  _destroySlotGameObjects() {
357
- var _a;
358
- for (const [gameObject] of this._slotGameObjects) {
409
+ for (const [gameObject, entry] of this._slotGameObjects) {
359
410
  if (!gameObject.destroyed) {
360
- // 先从 spine 插槽移除,避免 destroy 时重复操作
361
- const container = (_a = this._containerManager) === null || _a === void 0 ? void 0 : _a.getContainer(gameObject.id);
362
- if (container && this.armature) {
363
- this.armature.removeSlotObject(container);
411
+ // 先从 spine 插槽移除 wrapper,避免 destroy 时重复操作
412
+ if (this.armature) {
413
+ this.armature.removeSlotObject(entry.wrapper);
364
414
  }
415
+ entry.wrapper.destroy({ children: false });
365
416
  gameObject.destroy();
366
417
  }
367
418
  }
368
419
  this._slotGameObjects.clear();
420
+ this._pendingSlotObjects = [];
369
421
  }
370
422
  }
371
423
  /** 组件名称 */
@@ -450,6 +502,8 @@ let SpineSystem = class SpineSystem extends Renderer {
450
502
  super(...arguments);
451
503
  /** 骨架实例映射表(游戏对象 ID -> 骨架容器) */
452
504
  this.armatures = {};
505
+ /** Spine 组件实例映射(游戏对象 ID -> Spine 组件) */
506
+ this._spineComponents = {};
453
507
  }
454
508
  /**
455
509
  * 初始化系统
@@ -506,6 +560,10 @@ let SpineSystem = class SpineSystem extends Renderer {
506
560
  // @ts-ignore
507
561
  this.armatures[key].update(e.deltaTime * 0.001);
508
562
  }
563
+ // 处理等待容器就绪的 slot 挂载请求
564
+ for (let key in this._spineComponents) {
565
+ this._spineComponents[key]._flushPendingSlotObjects();
566
+ }
509
567
  super.update();
510
568
  }
511
569
  componentChanged(changed) {
@@ -571,6 +629,7 @@ let SpineSystem = class SpineSystem extends Renderer {
571
629
  autoUpdate: false,
572
630
  });
573
631
  this.armatures[changed.gameObject.id] = armature;
632
+ this._spineComponents[changed.gameObject.id] = component;
574
633
  if (changed.gameObject && changed.gameObject.transform) {
575
634
  const tran = changed.gameObject.transform;
576
635
  armature.x = tran.size.width * tran.origin.x;
@@ -634,6 +693,7 @@ let SpineSystem = class SpineSystem extends Renderer {
634
693
  }
635
694
  component.armature = null;
636
695
  delete this.armatures[changed.gameObject.id];
696
+ delete this._spineComponents[changed.gameObject.id];
637
697
  if (changed.type === OBSERVER_TYPE.CHANGE) ;
638
698
  });
639
699
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eva/spine-base",
3
- "version": "2.0.1-beta.39",
3
+ "version": "2.0.1-beta.40",
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.0.1-beta.39",
22
- "@eva/plugin-renderer": "2.0.1-beta.39",
21
+ "@eva/eva.js": "2.0.1-beta.40",
22
+ "@eva/plugin-renderer": "2.0.1-beta.40",
23
23
  "@eva/inspector-decorator": "^0.0.5",
24
24
  "pixi.js": "^8.17.0"
25
25
  }
@@ -1 +0,0 @@
1
- function _extends(){return _extends=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var n in a)({}).hasOwnProperty.call(a,n)&&(e[n]=a[n])}return e},_extends.apply(null,arguments)}globalThis.EVA=globalThis.EVA||{},globalThis.EVA.plugin=globalThis.EVA.plugin||{};var _EVA_IIFE_spineBase=function(e,t,a){"use strict";function n(e,t,a,n){var r,i=arguments.length,o=i<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,a):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,a,n);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(o=(i<3?r(o):i>3?r(t,a,o):r(t,a))||o);return i>3&&o&&Object.defineProperty(t,a,o),o}function r(e,t,a,n){return new(a||(a=Promise))((function(r,i){function o(e){try{c(n.next(e))}catch(e){i(e)}}function s(e){try{c(n.throw(e))}catch(e){i(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof a?t:new a((function(e){e(t)}))).then(o,s)}c((n=n.apply(e,t||[])).next())}))}function i(e){return function(t,a){var n=function(e,t){return e.constructor.IDEProps||(e.constructor.IDEProps={}),e.constructor.IDEProps[t]||(e.constructor.IDEProps[t]={}),e.constructor.IDEProps[t]}(t,a);n.key=a,n.type=e}}class o extends t.Component{constructor(){super(...arguments),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this._slotGameObjects=new Map,this.waitExecuteInfos=[]}set armature(e){if(this._armature=e,e){this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:a,track:n}=e;this.play(t,a,n)}else this.stop(e.track);this.waitExecuteInfos=[]}}get armature(){return this._armature}init(e){e&&_extends(this,e)}onDestroy(){this.destroied=!0}play(e,t,a){try{const n=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===a&&(a=0),this.armature.state.setAnimation(a,this.animationName,n)):this.waitExecuteInfos.push({playType:!0,name:e,loop:n,track:a})}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})}addAnimation(e,t,a,n){try{this.armature&&(void 0===n&&(n=0),this.armature.state.addAnimation(n,e,a,t))}catch(e){console.log(e)}}setMix(e,t,a){this.armature&&this.armature.state.data.setMix(e,t,a)}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,a){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 n=this._containerManager.getContainer(t.id);n?(this.armature.addSlotObject(e,n,a),this._slotGameObjects.set(t,e)):console.warn("GameObject does not have a render container")}removeSlotObject(e){if(!this.armature)return;if(!this._containerManager)return;const t=this._containerManager.getContainer(e.id);t&&this.armature.removeSlotObject(t),this._slotGameObjects.delete(e)}_destroySlotGameObjects(){var e;for(const[t]of this._slotGameObjects)if(!t.destroyed){const a=null===(e=this._containerManager)||void 0===e?void 0:e.getContainer(t.id);a&&this.armature&&this.armature.removeSlotObject(a),t.destroy()}this._slotGameObjects.clear()}}o.componentName="Spine",n([i("string")],o.prototype,"resource",void 0),n([i("number")],o.prototype,"scale",void 0),n([i("string")],o.prototype,"animationName",void 0),n([i("boolean")],o.prototype,"autoPlay",void 0),n([i("boolean")],o.prototype,"keepResource",void 0);let s={};function c(e,t,a){return r(this,void 0,void 0,(function*(){let n=s[e.name];if(!n)if(e.complete)n=function(e,t,a,n){const r=t.ske,i=t.atlas,o=new n.AtlasAttachmentLoader(i),c=r instanceof Uint8Array?new n.SkeletonBinary(o):new n.SkeletonJson(o);c.scale=a||1;const u={spineData:c.readSkeletonData(r),ref:0,imageSrc:t.image.label};return s[e]=u,u}(e.name,e.data,t,a);else if(!n)return;return n.ref++,n.spineData}))}let u=class extends a.Renderer{constructor(){super(...arguments),this.armatures={}}init({pixiSpine:e}){this.renderSystem=this.game.getSystem(a.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=e,this.game.canvas.addEventListener("webglcontextrestored",(()=>{const e=this.game.gameObjects;let a=[];for(let n in this.armatures){const r=+n;for(let n=0;n<e.length;++n){let i=e[n];if(i.id===r){let e=i.getComponent(o);e&&(this.remove({type:t.OBSERVER_TYPE.REMOVE,gameObject:i,component:e,componentName:o.componentName}),a.push({type:t.OBSERVER_TYPE.ADD,gameObject:i,component:e,componentName:o.componentName}));break}}}setTimeout((()=>{a.forEach((e=>{this.add(e)}))}),1e3)}),!1)}update(e){for(let t in this.armatures)this.armatures[t].update(.001*e.deltaTime);super.update()}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,a){var n,i,o;return r(this,void 0,void 0,(function*(){const r=e.component;clearTimeout(r.addHandler);const s=e.gameObject.id,u=this.increaseAsyncId(s),m=yield t.resource.getResource(r.resource);if(!this.validateAsyncId(s,u))return;const d=yield c(m,r.scale,this.pixiSpine);if(!this.validateAsyncId(s,u))return;if(!d)return void(r.addHandler=setTimeout((()=>{r.destroied||(void 0===a&&(a=20),--a>0?this.add(e,a):console.log("retry exceed max times",r.resource))}),1e3));this.remove(e);const l=null===(i=null===(n=this.renderSystem)||void 0===n?void 0:n.containerManager)||void 0===i?void 0:i.getContainer(e.gameObject.id);if(!l)return;r.lastResource=r.resource;const h=new this.pixiSpine.Spine({skeletonData:d,autoUpdate:!1});if(this.armatures[e.gameObject.id]=h,e.gameObject&&e.gameObject.transform){const t=e.gameObject.transform;h.x=t.size.width*t.origin.x,h.y=t.size.height*t.origin.y}l.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(e){var a,n,i,o,c,u;return r(this,void 0,void 0,(function*(){this.increaseAsyncId(e.gameObject.id);const m=e.component;clearTimeout(m.addHandler);const d=this.armatures[e.gameObject.id],l=null===(n=null===(a=this.renderSystem)||void 0===a?void 0:a.containerManager)||void 0===n?void 0:n.getContainer(e.gameObject.id);if(l&&d&&l.removeChild(d),m.armature&&(m._destroySlotGameObjects(),m.armature.destroy({children:!0}),!m.keepResource)){const e=yield t.resource.getResource(m.lastResource);(null===(o=null===(i=e.data)||void 0===i?void 0:i.image)||void 0===o?void 0:o.src)||null===(u=null===(c=e.data)||void 0===c?void 0:c.image)||void 0===u||u.label,function(e){const a=e.name,n=s[a];n&&(n.ref--,setTimeout((()=>r(this,void 0,void 0,(function*(){n.ref<=0&&(t.resource.destroy(a),delete s[a])}))),100))}(e)}m.armature=null,delete this.armatures[e.gameObject.id],e.type,t.OBSERVER_TYPE.CHANGE}))}};u.systemName="SpineSystem",u=n([t.decorators.componentObserver({Spine:["resource"]})],u);var m=u;return t.resource.registerResourceType("SPINE"),e.Spine=o,e.SpineSystem=m,Object.defineProperty(e,"__esModule",{value:!0}),e}({},EVA,EVA.plugin.renderer);globalThis.EVA.plugin.spineBase=globalThis.EVA.plugin.spineBase||_EVA_IIFE_spineBase;
package/dist/global.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import "@eva/eva.js";
2
- declare module "@eva/eva.js" {
3
- export enum RESOURCE_TYPE {
4
- 'SPINE' = 'SPINE'
5
- }
6
- }
@@ -1,16 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@eva/eva.js"),t=require("@eva/plugin-renderer"),a=require("@eva/inspector-decorator");
2
- /*! *****************************************************************************
3
- Copyright (c) Microsoft Corporation. All rights reserved.
4
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
5
- this file except in compliance with the License. You may obtain a copy of the
6
- License at http://www.apache.org/licenses/LICENSE-2.0
7
-
8
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
9
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
10
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
11
- MERCHANTABLITY OR NON-INFRINGEMENT.
12
-
13
- See the Apache Version 2.0 License for specific language governing permissions
14
- and limitations under the License.
15
- ***************************************************************************** */
16
- function r(e,t,a,r){var i,n=arguments.length,o=n<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,a):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,a,r);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(n<3?i(o):n>3?i(t,a,o):i(t,a))||o);return n>3&&o&&Object.defineProperty(t,a,o),o}function i(e,t,a,r){return new(a||(a=Promise))((function(i,n){function o(e){try{c(r.next(e))}catch(e){n(e)}}function s(e){try{c(r.throw(e))}catch(e){n(e)}}function c(e){e.done?i(e.value):new a((function(t){t(e.value)})).then(o,s)}c((r=r.apply(e,t||[])).next())}))}class n extends e.Component{constructor(){super(...arguments),this.resource="",this.scale=1,this.animationName="",this.autoPlay=!0,this.keepResource=!1,this._slotGameObjects=new Map,this.waitExecuteInfos=[]}set armature(e){if(this._armature=e,e){this.autoPlay&&this.play(this.animationName);for(const e of this.waitExecuteInfos)if(e.playType){const{name:t,loop:a,track:r}=e;this.play(t,a,r)}else this.stop(e.track);this.waitExecuteInfos=[]}}get armature(){return this._armature}init(e){e&&Object.assign(this,e)}onDestroy(){this.destroied=!0}play(e,t,a){try{const r=null!=t?t:this.autoPlay;e&&(this.animationName=e),this.armature?(void 0===a&&(a=0),this.armature.state.setAnimation(a,this.animationName,r)):this.waitExecuteInfos.push({playType:!0,name:e,loop:r,track:a})}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})}addAnimation(e,t,a,r){try{this.armature&&(void 0===r&&(r=0),this.armature.state.addAnimation(r,e,a,t))}catch(e){console.log(e)}}setMix(e,t,a){this.armature&&this.armature.state.data.setMix(e,t,a)}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,a){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 r=this._containerManager.getContainer(t.id);r?(this.armature.addSlotObject(e,r,a),this._slotGameObjects.set(t,e)):console.warn("GameObject does not have a render container")}removeSlotObject(e){if(!this.armature)return;if(!this._containerManager)return;const t=this._containerManager.getContainer(e.id);t&&this.armature.removeSlotObject(t),this._slotGameObjects.delete(e)}_destroySlotGameObjects(){var e;for(const[t]of this._slotGameObjects)if(!t.destroyed){const a=null===(e=this._containerManager)||void 0===e?void 0:e.getContainer(t.id);a&&this.armature&&this.armature.removeSlotObject(a),t.destroy()}this._slotGameObjects.clear()}}n.componentName="Spine",r([a.type("string")],n.prototype,"resource",void 0),r([a.type("number")],n.prototype,"scale",void 0),r([a.type("string")],n.prototype,"animationName",void 0),r([a.type("boolean")],n.prototype,"autoPlay",void 0),r([a.type("boolean")],n.prototype,"keepResource",void 0);let o={};function s(e,t,a){return i(this,void 0,void 0,(function*(){let r=o[e.name];if(!r)if(e.complete)r=function(e,t,a,r){const i=t.ske,n=t.atlas,s=new r.AtlasAttachmentLoader(n),c=i instanceof Uint8Array?new r.SkeletonBinary(s):new r.SkeletonJson(s);c.scale=a||1;const m={spineData:c.readSkeletonData(i),ref:0,imageSrc:t.image.label};return o[e]=m,m}(e.name,e.data,t,a);else if(!r)return;return r.ref++,r.spineData}))}let c=class extends t.Renderer{constructor(){super(...arguments),this.armatures={}}init({pixiSpine:a}){this.renderSystem=this.game.getSystem(t.RendererSystem),this.renderSystem.rendererManager.register(this),this.pixiSpine=a,this.game.canvas.addEventListener("webglcontextrestored",(()=>{const t=this.game.gameObjects;let a=[];for(let r in this.armatures){const i=+r;for(let r=0;r<t.length;++r){let o=t[r];if(o.id===i){let t=o.getComponent(n);t&&(this.remove({type:e.OBSERVER_TYPE.REMOVE,gameObject:o,component:t,componentName:n.componentName}),a.push({type:e.OBSERVER_TYPE.ADD,gameObject:o,component:t,componentName:n.componentName}));break}}}setTimeout((()=>{a.forEach((e=>{this.add(e)}))}),1e3)}),!1)}update(e){for(let t in this.armatures)this.armatures[t].update(.001*e.deltaTime);super.update()}componentChanged(t){return i(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,a){var r,n,o;return i(this,void 0,void 0,(function*(){const i=t.component;clearTimeout(i.addHandler);const c=t.gameObject.id,m=this.increaseAsyncId(c),d=yield e.resource.getResource(i.resource);if(!this.validateAsyncId(c,m))return;const u=yield s(d,i.scale,this.pixiSpine);if(!this.validateAsyncId(c,m))return;if(!u)return void(i.addHandler=setTimeout((()=>{i.destroied||(void 0===a&&(a=20),--a>0?this.add(t,a):console.log("retry exceed max times",i.resource))}),1e3));this.remove(t);const l=null===(n=null===(r=this.renderSystem)||void 0===r?void 0:r.containerManager)||void 0===n?void 0:n.getContainer(t.gameObject.id);if(!l)return;i.lastResource=i.resource;const h=new this.pixiSpine.Spine({skeletonData:u,autoUpdate:!1});if(this.armatures[t.gameObject.id]=h,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}l.addChildAt(h,0),h.update(),i._containerManager=null===(o=this.renderSystem)||void 0===o?void 0:o.containerManager,i.armature=h,i.emit("loaded",{resource:i.resource}),h.state.addListener({start:(e,t)=>{i.emit("start",{track:e,name:e.animation.name})},complete:(e,t)=>{i.emit("complete",{track:e,name:e.animation.name})},interrupt:(e,t)=>{i.emit("interrupt",{track:e,name:e.animation.name})},end:(e,t)=>{i.emit("end",{track:e,name:e.animation.name})},event:(e,t)=>{i.emit("event",e,t)}})}))}change(e){this.remove(e),this.add(e)}remove(t){var a,r,n,s,c,m;return i(this,void 0,void 0,(function*(){this.increaseAsyncId(t.gameObject.id);const d=t.component;clearTimeout(d.addHandler);const u=this.armatures[t.gameObject.id],l=null===(r=null===(a=this.renderSystem)||void 0===a?void 0:a.containerManager)||void 0===r?void 0:r.getContainer(t.gameObject.id);if(l&&u&&l.removeChild(u),d.armature&&(d._destroySlotGameObjects(),d.armature.destroy({children:!0}),!d.keepResource)){const t=yield e.resource.getResource(d.lastResource);(null===(s=null===(n=t.data)||void 0===n?void 0:n.image)||void 0===s?void 0:s.src)||null===(m=null===(c=t.data)||void 0===c?void 0:c.image)||void 0===m||m.label,function(t){const a=t.name,r=o[a];r&&(r.ref--,setTimeout((()=>i(this,void 0,void 0,(function*(){r.ref<=0&&(e.resource.destroy(a),delete o[a])}))),100))}(t)}d.armature=null,delete this.armatures[t.gameObject.id],t.type,e.OBSERVER_TYPE.CHANGE}))}};c.systemName="SpineSystem",c=r([e.decorators.componentObserver({Spine:["resource"]})],c);var m=c;e.resource.registerResourceType("SPINE"),exports.Spine=n,exports.SpineSystem=m;
@@ -1,262 +0,0 @@
1
- /// <reference path="./global.d.ts"/>
2
- import { Component } from '@eva/eva.js';
3
- import { ComponentChanged } from '@eva/eva.js';
4
- import { Container } from 'pixi.js';
5
- import { ContainerManager } from '@eva/plugin-renderer';
6
- import { GameObject } from '@eva/eva.js';
7
- import { Renderer } from '@eva/plugin-renderer';
8
- import { RendererManager } from '@eva/plugin-renderer';
9
- import { RendererSystem } from '@eva/plugin-renderer';
10
- import { UpdateParams } from '@eva/eva.js';
11
-
12
- /**
13
- * Spine 骨骼动画组件
14
- *
15
- * Spine 组件用于播放 Esoteric Software 的 Spine 骨骼动画。
16
- * 支持骨骼动画播放控制、动画混合、附件替换等高级功能,
17
- * 适用于角色动画、复杂特效等需要骨骼动画的场景。
18
- *
19
- * 主要功能:
20
- * - 骨骼动画播放和控制
21
- * - 动画轨道管理(多动画并行)
22
- * - 动画混合过渡
23
- * - 骨骼和附件访问
24
- * - 支持 Spine 3.6 和 3.8 版本
25
- *
26
- * @example
27
- * ```typescript
28
- * // 创建 Spine 动画
29
- * const character = new GameObject('character');
30
- * const spine = new Spine({
31
- * resource: 'heroSpine', // Spine 资源
32
- * animationName: 'idle', // 默认动画
33
- * autoPlay: true, // 自动播放
34
- * scale: 0.5 // 缩放比例
35
- * });
36
- * character.addComponent(spine);
37
- *
38
- * // 播放动画
39
- * spine.play('walk', true); // 循环播放 walk 动画
40
- *
41
- * // 停止动画
42
- * spine.stop();
43
- *
44
- * // 动画混合
45
- * spine.setMix('idle', 'walk', 0.3); // 设置过渡时间
46
- * spine.play('walk');
47
- *
48
- * // 添加动画队列
49
- * spine.play('attack', false); // 播放攻击动画
50
- * spine.addAnimation('idle', 0, true); // 攻击完成后回到 idle
51
- *
52
- * // 替换附件(换装)
53
- * spine.setAttachment('weapon', 'sword'); // 将武器槽替换为剑
54
- *
55
- * // 访问骨骼
56
- * const headBone = spine.getBone('head');
57
- * if (headBone) {
58
- * headBone.rotation = 15; // 旋转头部
59
- * }
60
- *
61
- * // 多轨道动画
62
- * spine.play('walk', true, 0); // 轨道0:身体动画
63
- * spine.play('shoot', false, 1); // 轨道1:上半身动画
64
- * ```
65
- */
66
- export declare class Spine extends Component<SpineParams> {
67
- /** 组件名称 */
68
- static componentName: string;
69
- /** Spine 资源名称 */
70
- resource: string;
71
- /** 动画缩放比例 */
72
- scale: number;
73
- /** 当前播放的动画名称 */
74
- animationName: string;
75
- /** 是否自动播放动画 */
76
- autoPlay: boolean;
77
- /** 是否保留资源(销毁时不释放) */
78
- keepResource: boolean;
79
- /** Spine 骨架实例(内部使用) */
80
- private _armature;
81
- /** 容器管理器引用(由 SpineSystem 设置) */
82
- _containerManager: any;
83
- /** 挂载到插槽的 GameObject 映射(GameObject -> slot 标识) */
84
- private _slotGameObjects;
85
- /** 等待执行的动画操作队列 */
86
- private waitExecuteInfos;
87
- /**
88
- * 设置骨架实例
89
- * 当骨架加载完成后自动执行等待队列中的动画操作
90
- */
91
- set armature(val: any);
92
- /** 获取骨架实例 */
93
- get armature(): any;
94
- /** 组件是否已销毁 */
95
- destroied: boolean;
96
- /** 动画事件处理器 */
97
- addHandler: any;
98
- /** 上一次使用的资源名称 */
99
- lastResource: string;
100
- /**
101
- * 初始化组件
102
- * @param obj - 初始化参数
103
- * @param obj.resource - Spine 资源名称
104
- * @param obj.animationName - 默认动画名称
105
- * @param obj.scale - 缩放比例
106
- * @param obj.autoPlay - 是否自动播放
107
- */
108
- init(obj?: SpineParams): void;
109
- /** 组件销毁时调用 */
110
- onDestroy(): void;
111
- /**
112
- * 播放指定动画
113
- *
114
- * 如果骨架尚未加载完成,动画操作将被加入等待队列。
115
- *
116
- * @param name - 动画名称,不指定则使用 animationName 属性
117
- * @param loopAnimation - 是否循环播放,默认跟随 autoPlay 属性
118
- * @param track - 动画轨道编号,默认为 0
119
- */
120
- play(name?: string, loopAnimation?: boolean, track?: number): void;
121
- /**
122
- * 停止指定轨道的动画
123
- *
124
- * 如果骨架尚未加载完成,停止操作将被加入等待队列。
125
- *
126
- * @param track - 动画轨道编号,默认为 0
127
- */
128
- stop(track?: number): void;
129
- /**
130
- * 在当前动画之后添加新动画到队列
131
- *
132
- * 用于创建动画序列,当前动画播放完毕后自动播放下一个动画。
133
- *
134
- * @param name - 动画名称
135
- * @param delay - 延迟时间(秒)
136
- * @param loop - 是否循环播放
137
- * @param track - 动画轨道编号,默认为 0
138
- */
139
- addAnimation(name?: string, delay?: number, loop?: boolean, track?: number): void;
140
- /**
141
- * 设置两个动画之间的混合过渡时间
142
- *
143
- * 当从一个动画切换到另一个动画时,会在指定时间内进行平滑过渡。
144
- *
145
- * @param from - 起始动画名称
146
- * @param to - 目标动画名称
147
- * @param duration - 过渡时长(秒)
148
- */
149
- setMix(from: string, to: string, duration: number): void;
150
- /**
151
- * 获取指定轨道当前播放的动画名称
152
- *
153
- * @param track - 动画轨道编号,默认为 0
154
- * @returns 动画名称,如果未找到则返回 undefined
155
- */
156
- getAnim(track?: number): any;
157
- /**
158
- * 设置默认的动画混合时间
159
- *
160
- * 当没有为特定动画对指定混合时间时,将使用此默认值。
161
- *
162
- * @param duration - 默认混合时长(秒)
163
- */
164
- setDefaultMix(duration: number): void;
165
- /**
166
- * 替换指定插槽的附件
167
- *
168
- * 用于换装、武器切换等场景。
169
- *
170
- * @param slotName - 插槽名称
171
- * @param attachmentName - 附件名称
172
- */
173
- setAttachment(slotName: string, attachmentName: string): void;
174
- /**
175
- * 获取指定名称的骨骼
176
- *
177
- * 可用于直接操作骨骼的位置、旋转、缩放等属性。
178
- *
179
- * @param boneName - 骨骼名称
180
- * @returns 骨骼对象,如果未找到则返回 undefined
181
- */
182
- getBone(boneName: string): any;
183
- /**
184
- * 将一个 GameObject 挂载到 Spine 的指定插槽上
185
- *
186
- * 挂载后 GameObject 会跟随骨骼运动。当 Spine 组件销毁时,
187
- * 挂载的 GameObject 也会被自动销毁。
188
- *
189
- * @param slot - 插槽名称或索引
190
- * @param gameObject - 要挂载的 GameObject
191
- * @param options - 可选配置
192
- * @param options.followAttachmentTimeline - 是否跟随插槽的附件时间线
193
- */
194
- addSlotObject(slot: number | string, gameObject: GameObject, options?: {
195
- followAttachmentTimeline?: boolean;
196
- }): void;
197
- /**
198
- * 从插槽上移除挂载的 GameObject
199
- *
200
- * @param gameObject - 要移除的 GameObject
201
- */
202
- removeSlotObject(gameObject: GameObject): void;
203
- /**
204
- * 销毁所有挂载到插槽的 GameObject(内部使用)
205
- */
206
- _destroySlotGameObjects(): void;
207
- }
208
-
209
- export declare interface SpineParams {
210
- resource: string;
211
- animationName?: string;
212
- scale?: number;
213
- autoPlay?: boolean;
214
- }
215
-
216
- /**
217
- * Spine 骨骼动画系统
218
- *
219
- * SpineSystem 负责管理所有 Spine 组件的骨架创建、动画更新和资源管理。
220
- * 系统会监听 Spine 组件的变化,自动加载骨骼数据并创建动画实例,
221
- * 并在每帧更新所有活跃的 Spine 动画。
222
- *
223
- * 主要功能:
224
- * - 骨骼数据加载和缓存
225
- * - 动画实例创建和销毁
226
- * - 每帧动画状态更新
227
- * - WebGL 上下文恢复处理
228
- * - 资源重试机制
229
- */
230
- export declare class SpineSystem extends Renderer {
231
- /** 系统名称 */
232
- static systemName: string;
233
- /** 骨架实例映射表(游戏对象 ID -> 骨架容器) */
234
- armatures: Record<number, Container>;
235
- /** 渲染系统引用 */
236
- renderSystem: RendererSystem;
237
- /** 渲染器管理器 */
238
- rendererManager: RendererManager;
239
- /** 容器管理器 */
240
- containerManager: ContainerManager;
241
- /** PixiJS Spine 插件实例 */
242
- pixiSpine: any;
243
- /**
244
- * 初始化系统
245
- * @param obj - 初始化参数
246
- * @param obj.pixiSpine - PixiJS Spine 插件实例
247
- */
248
- init({ pixiSpine }: {
249
- pixiSpine: any;
250
- }): void;
251
- /**
252
- * 每帧更新所有 Spine 动画
253
- * @param e - 更新参数,包含帧间隔时间
254
- */
255
- update(e: UpdateParams): void;
256
- componentChanged(changed: ComponentChanged): Promise<void>;
257
- add(changed: ComponentChanged, count?: number): Promise<void>;
258
- change(changed: ComponentChanged): void;
259
- remove(changed: ComponentChanged): Promise<void>;
260
- }
261
-
262
- export { }