@melonjs/spine-plugin 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  /*!
2
- * melonJS Spine plugin - v1.4.0
2
+ * melonJS Spine plugin - v1.5.0
3
3
  * http://www.melonjs.org
4
4
  * @melonjs/spine-plugin is licensed under the MIT License.
5
5
  * http://www.opensource.org/licenses/mit-license
6
6
  * @copyright (C) 2011 - 2023 AltByte Pte Ltd
7
7
  */
8
- import { event, video, Color as Color$1, Polygon, Math as Math$1, utils, loader, Renderable as Renderable$1, Vector2d } from 'melonjs';
8
+ import { Color as Color$1, Polygon, Math as Math$1, loader, utils, plugin, Renderable as Renderable$1, Vector2d } from 'melonjs';
9
9
 
10
10
  /******************************************************************************
11
11
  * Spine Runtimes License Agreement
@@ -11276,59 +11276,6 @@ class ManagedWebGLRenderingContext {
11276
11276
  this.restorables.splice(index, 1);
11277
11277
  }
11278
11278
  }
11279
- const ONE = 1;
11280
- const ONE_MINUS_SRC_COLOR = 0x0301;
11281
- const SRC_ALPHA = 0x0302;
11282
- const ONE_MINUS_SRC_ALPHA = 0x0303;
11283
- const ONE_MINUS_DST_ALPHA = 0x0305;
11284
- const DST_COLOR = 0x0306;
11285
- class WebGLBlendModeConverter {
11286
- static getDestGLBlendMode(blendMode) {
11287
- switch (blendMode) {
11288
- case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA;
11289
- case BlendMode.Additive: return ONE;
11290
- case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
11291
- case BlendMode.Screen: return ONE_MINUS_SRC_ALPHA;
11292
- default: throw new Error("Unknown blend mode: " + blendMode);
11293
- }
11294
- }
11295
- static getDestColorGLBlendMode(blendMode) {
11296
- switch (blendMode) {
11297
- case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA;
11298
- case BlendMode.Additive: return ONE;
11299
- case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
11300
- case BlendMode.Screen: return ONE_MINUS_SRC_COLOR;
11301
- default: throw new Error("Unknown blend mode: " + blendMode);
11302
- }
11303
- }
11304
- static getDestAlphaGLBlendMode(blendMode, premultipliedAlpha = false) {
11305
- switch (blendMode) {
11306
- case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA;
11307
- case BlendMode.Additive: return premultipliedAlpha ? ONE_MINUS_SRC_ALPHA : ONE;
11308
- case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
11309
- case BlendMode.Screen: return ONE_MINUS_SRC_ALPHA;
11310
- default: throw new Error("Unknown blend mode: " + blendMode);
11311
- }
11312
- }
11313
- static getSourceColorGLBlendMode(blendMode, premultipliedAlpha = false) {
11314
- switch (blendMode) {
11315
- case BlendMode.Normal: return premultipliedAlpha ? ONE : SRC_ALPHA;
11316
- case BlendMode.Additive: return premultipliedAlpha ? ONE : SRC_ALPHA;
11317
- case BlendMode.Multiply: return DST_COLOR;
11318
- case BlendMode.Screen: return premultipliedAlpha ? ONE : SRC_ALPHA;
11319
- default: throw new Error("Unknown blend mode: " + blendMode);
11320
- }
11321
- }
11322
- static getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha = false) {
11323
- switch (blendMode) {
11324
- case BlendMode.Normal: return premultipliedAlpha ? SRC_ALPHA : ONE;
11325
- case BlendMode.Additive: return premultipliedAlpha ? SRC_ALPHA : ONE;
11326
- case BlendMode.Multiply: return ONE;
11327
- case BlendMode.Screen: return ONE;
11328
- default: throw new Error("Unknown blend mode: " + blendMode);
11329
- }
11330
- }
11331
- }
11332
11279
 
11333
11280
  /******************************************************************************
11334
11281
  * Spine Runtimes License Agreement
@@ -12778,6 +12725,12 @@ var VertexAttributeType;
12778
12725
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
12779
12726
  * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12780
12727
  *****************************************************************************/
12728
+ const GL_ONE = 1;
12729
+ const GL_ONE_MINUS_SRC_COLOR = 0x0301;
12730
+ const GL_SRC_ALPHA = 0x0302;
12731
+ const GL_ONE_MINUS_SRC_ALPHA = 0x0303;
12732
+ const GL_ONE_MINUS_DST_ALPHA = 0x0305;
12733
+ const GL_DST_COLOR = 0x0306;
12781
12734
  class PolygonBatcher {
12782
12735
  constructor(context, twoColorTint = true, maxVertices = 10920) {
12783
12736
  this.drawCalls = 0;
@@ -12797,8 +12750,7 @@ class PolygonBatcher {
12797
12750
  let gl = this.context.gl;
12798
12751
  this.srcColorBlend = gl.SRC_ALPHA;
12799
12752
  this.srcAlphaBlend = gl.ONE;
12800
- this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA;
12801
- this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA;
12753
+ this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
12802
12754
  }
12803
12755
  begin(shader) {
12804
12756
  if (this.isDrawing)
@@ -12809,25 +12761,28 @@ class PolygonBatcher {
12809
12761
  this.isDrawing = true;
12810
12762
  let gl = this.context.gl;
12811
12763
  gl.enable(gl.BLEND);
12812
- gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend);
12764
+ gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
12813
12765
  if (PolygonBatcher.disableCulling) {
12814
12766
  this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);
12815
12767
  if (this.cullWasEnabled)
12816
12768
  gl.disable(gl.CULL_FACE);
12817
12769
  }
12818
12770
  }
12819
- setBlendMode(srcColorBlend, srcAlphaBlend, dstColorBlend, dstAlphaBlend) {
12820
- if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstColorBlend == dstColorBlend && this.dstAlphaBlend == dstAlphaBlend)
12771
+ setBlendMode(blendMode, premultipliedAlpha) {
12772
+ const blendModeGL = PolygonBatcher.blendModesGL[blendMode];
12773
+ const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb;
12774
+ const srcAlphaBlend = blendModeGL.srcAlpha;
12775
+ const dstBlend = blendModeGL.dstRgb;
12776
+ if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend)
12821
12777
  return;
12822
12778
  this.srcColorBlend = srcColorBlend;
12823
12779
  this.srcAlphaBlend = srcAlphaBlend;
12824
- this.dstColorBlend = dstColorBlend;
12825
- this.dstAlphaBlend = dstAlphaBlend;
12780
+ this.dstBlend = dstBlend;
12826
12781
  if (this.isDrawing) {
12827
12782
  this.flush();
12828
- let gl = this.context.gl;
12829
- gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend);
12830
12783
  }
12784
+ let gl = this.context.gl;
12785
+ gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
12831
12786
  }
12832
12787
  draw(texture, vertices, indices) {
12833
12788
  if (texture != this.lastTexture) {
@@ -12893,6 +12848,12 @@ class PolygonBatcher {
12893
12848
  }
12894
12849
  PolygonBatcher.disableCulling = false;
12895
12850
  PolygonBatcher.globalDrawCalls = 0;
12851
+ PolygonBatcher.blendModesGL = [
12852
+ { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },
12853
+ { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE },
12854
+ { srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },
12855
+ { srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE }
12856
+ ];
12896
12857
 
12897
12858
  /******************************************************************************
12898
12859
  * Spine Runtimes License Agreement
@@ -12937,8 +12898,7 @@ class ShapeRenderer {
12937
12898
  let gl = this.context.gl;
12938
12899
  this.srcColorBlend = gl.SRC_ALPHA;
12939
12900
  this.srcAlphaBlend = gl.ONE;
12940
- this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA;
12941
- this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA;
12901
+ this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
12942
12902
  }
12943
12903
  begin(shader) {
12944
12904
  if (this.isDrawing)
@@ -12948,17 +12908,16 @@ class ShapeRenderer {
12948
12908
  this.isDrawing = true;
12949
12909
  let gl = this.context.gl;
12950
12910
  gl.enable(gl.BLEND);
12951
- gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend);
12911
+ gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
12952
12912
  }
12953
- setBlendMode(srcColorBlend, srcAlphaBlend, dstColorBlend, dstAlphaBlend) {
12913
+ setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) {
12954
12914
  this.srcColorBlend = srcColorBlend;
12955
12915
  this.srcAlphaBlend = srcAlphaBlend;
12956
- this.dstColorBlend = dstColorBlend;
12957
- this.dstAlphaBlend = dstAlphaBlend;
12916
+ this.dstBlend = dstBlend;
12958
12917
  if (this.isDrawing) {
12959
12918
  this.flush();
12960
12919
  let gl = this.context.gl;
12961
- gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend);
12920
+ gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
12962
12921
  }
12963
12922
  }
12964
12923
  setColor(color) {
@@ -13293,7 +13252,7 @@ class SkeletonDebugRenderer {
13293
13252
  let skeletonY = skeleton.y;
13294
13253
  let gl = this.context.gl;
13295
13254
  let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;
13296
- shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
13255
+ shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
13297
13256
  let bones = skeleton.bones;
13298
13257
  if (this.drawBones) {
13299
13258
  shapes.setColor(this.boneLineColor);
@@ -13515,10 +13474,6 @@ let SkeletonRenderer$2 = class SkeletonRenderer {
13515
13474
  let premultipliedAlpha = this.premultipliedAlpha;
13516
13475
  let twoColorTint = this.twoColorTint;
13517
13476
  let blendMode = null;
13518
- let tempPos = this.temp;
13519
- let tempUv = this.temp2;
13520
- let tempLight = this.temp3;
13521
- let tempDark = this.temp4;
13522
13477
  let renderable = this.renderable;
13523
13478
  let uvs;
13524
13479
  let triangles;
@@ -13611,7 +13566,7 @@ let SkeletonRenderer$2 = class SkeletonRenderer {
13611
13566
  let slotBlendMode = slot.data.blendMode;
13612
13567
  if (slotBlendMode != blendMode) {
13613
13568
  blendMode = slotBlendMode;
13614
- batcher.setBlendMode(WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getDestColorGLBlendMode(blendMode), WebGLBlendModeConverter.getDestAlphaGLBlendMode(blendMode, premultipliedAlpha));
13569
+ batcher.setBlendMode(blendMode, premultipliedAlpha);
13615
13570
  }
13616
13571
  if (clipper.isClipping()) {
13617
13572
  clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
@@ -14207,7 +14162,7 @@ class LoadingScreen {
14207
14162
  let gl = renderer.context.gl;
14208
14163
  renderer.resize(ResizeMode.Expand);
14209
14164
  renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);
14210
- renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
14165
+ renderer.batcher.setBlendMode(BlendMode.Normal, true);
14211
14166
  if (complete) {
14212
14167
  this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);
14213
14168
  if (this.fadeOut > FADE_OUT)
@@ -14281,8 +14236,10 @@ let SPINE_LOGO_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAABsCAY
14281
14236
  class SpineCanvas {
14282
14237
  /** Constructs a new spine canvas, rendering to the provided HTML canvas. */
14283
14238
  constructor(canvas, config) {
14239
+ this.config = config;
14284
14240
  /** Tracks the current time, delta, and other time related statistics. */
14285
14241
  this.time = new TimeKeeper();
14242
+ this.disposed = false;
14286
14243
  if (!config.pathPrefix)
14287
14244
  config.pathPrefix = "";
14288
14245
  if (!config.app)
@@ -14292,6 +14249,7 @@ class SpineCanvas {
14292
14249
  update: () => { },
14293
14250
  render: () => { },
14294
14251
  error: () => { },
14252
+ dispose: () => { },
14295
14253
  };
14296
14254
  if (!config.webglConfig)
14297
14255
  config.webglConfig = { alpha: true };
@@ -14304,6 +14262,8 @@ class SpineCanvas {
14304
14262
  if (config.app.loadAssets)
14305
14263
  config.app.loadAssets(this);
14306
14264
  let loop = () => {
14265
+ if (this.disposed)
14266
+ return;
14307
14267
  requestAnimationFrame(loop);
14308
14268
  this.time.update();
14309
14269
  if (config.app.update)
@@ -14312,6 +14272,8 @@ class SpineCanvas {
14312
14272
  config.app.render(this);
14313
14273
  };
14314
14274
  let waitForAssets = () => {
14275
+ if (this.disposed)
14276
+ return;
14315
14277
  if (this.assetManager.isLoadingComplete()) {
14316
14278
  if (this.assetManager.hasErrors()) {
14317
14279
  if (config.app.error)
@@ -14333,6 +14295,12 @@ class SpineCanvas {
14333
14295
  this.gl.clearColor(r, g, b, a);
14334
14296
  this.gl.clear(this.gl.COLOR_BUFFER_BIT);
14335
14297
  }
14298
+ /** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/
14299
+ dispose() {
14300
+ if (this.config.app.dispose)
14301
+ this.config.app.dispose(this);
14302
+ this.disposed = true;
14303
+ }
14336
14304
  }
14337
14305
 
14338
14306
  var spineWebGL = {
@@ -14484,7 +14452,6 @@ var spineWebGL = {
14484
14452
  VertexAttachment: VertexAttachment,
14485
14453
  VertexAttribute: VertexAttribute,
14486
14454
  get VertexAttributeType () { return VertexAttributeType; },
14487
- WebGLBlendModeConverter: WebGLBlendModeConverter,
14488
14455
  WindowedMean: WindowedMean
14489
14456
  };
14490
14457
 
@@ -14912,71 +14879,6 @@ var spineCanvas = {
14912
14879
  WindowedMean: WindowedMean
14913
14880
  };
14914
14881
 
14915
- /**
14916
- * @classdesc
14917
- * An Asset Manager class to load spine assets
14918
- */
14919
- class AssetManager {
14920
- asset_manager;
14921
- pathPrefix;
14922
-
14923
- /**
14924
- * @param {string} [pathPrefix=""] - a default path prefix for assets location
14925
- */
14926
- constructor(pathPrefix = "") {
14927
- event.once(event.VIDEO_INIT, () => {
14928
- this.pathPrefix = pathPrefix;
14929
- if (video.renderer.WebGLVersion >= 1) {
14930
- this.asset_manager = new AssetManager$2(video.renderer.getContext(), this.pathPrefix);
14931
- } else {
14932
- // canvas renderer
14933
- this.asset_manager = new AssetManager$1(this.pathPrefix);
14934
- }
14935
- });
14936
- }
14937
-
14938
- /**
14939
- * set a default path prefix for assets location
14940
- * @see loadAsset
14941
- * @param {string} pathPrefix
14942
- */
14943
- setPrefix(pathPrefix) {
14944
- this.asset_manager.pathPrefix = this.pathPrefix = pathPrefix;
14945
- }
14946
-
14947
- /**
14948
- * define all spine assets to be loaded
14949
- * @see setPrefix
14950
- * @see loadAll
14951
- * @param {string} atlas
14952
- * @param {string} skel
14953
- * @example
14954
- * // load spine assets
14955
- * Spine.assetManager.setPrefix("data/spine/");
14956
- * Spine.assetManager.loadAsset("alien.atlas", "alien-ess.json");
14957
- * await Spine.assetManager.loadAll();
14958
- */
14959
- loadAsset(atlas, skel) {
14960
- if (atlas) {
14961
- this.asset_manager.loadTextureAtlas(atlas);
14962
- }
14963
-
14964
- if (skel.endsWith(".skel")) {
14965
- this.asset_manager.loadBinary(skel);
14966
- } else {
14967
- this.asset_manager.loadText(skel);
14968
- }
14969
- }
14970
-
14971
- /**
14972
- * load all defined spine assets
14973
- * @see loadAsset
14974
- */
14975
- loadAll() {
14976
- return this.asset_manager.loadAll();
14977
- }
14978
- }
14979
-
14980
14882
  const vertexSize = 2 + 2 + 4;
14981
14883
  const blendModeLUT = ["normal", "additive", "multiply", "screen"];
14982
14884
  const regionDebugColor = "green";
@@ -15196,7 +15098,7 @@ class SkeletonRenderer {
15196
15098
  }
15197
15099
 
15198
15100
  var name = "@melonjs/spine-plugin";
15199
- var version = "1.4.0";
15101
+ var version = "1.5.0";
15200
15102
  var description = "melonJS Spine plugin";
15201
15103
  var homepage = "https://github.com/melonjs/spine-plugin#readme";
15202
15104
  var type = "module";
@@ -15242,12 +15144,12 @@ var files = [
15242
15144
  "CHANGELOG.md"
15243
15145
  ];
15244
15146
  var peerDependencies = {
15245
- melonjs: "^15.10.0"
15147
+ melonjs: "^15.12.0"
15246
15148
  };
15247
15149
  var dependencies = {
15248
- "@esotericsoftware/spine-canvas": "^4.2.19",
15249
- "@esotericsoftware/spine-core": "^4.2.19",
15250
- "@esotericsoftware/spine-webgl": "^4.2.19"
15150
+ "@esotericsoftware/spine-canvas": "^4.2.23",
15151
+ "@esotericsoftware/spine-core": "^4.2.23",
15152
+ "@esotericsoftware/spine-webgl": "^4.2.23"
15251
15153
  };
15252
15154
  var devDependencies = {
15253
15155
  "@babel/eslint-parser": "^7.22.15",
@@ -15257,9 +15159,9 @@ var devDependencies = {
15257
15159
  "@rollup/plugin-node-resolve": "^15.2.1",
15258
15160
  "@rollup/plugin-replace": "^5.0.2",
15259
15161
  "del-cli": "^5.1.0",
15260
- eslint: "^8.48.0",
15261
- "eslint-plugin-jsdoc": "^46.5.1",
15262
- rollup: "^3.28.1",
15162
+ eslint: "^8.50.0",
15163
+ "eslint-plugin-jsdoc": "^46.8.2",
15164
+ rollup: "^3.29.2",
15263
15165
  "rollup-plugin-bundle-size": "^1.0.3",
15264
15166
  typescript: "^5.2.2"
15265
15167
  };
@@ -15296,60 +15198,195 @@ var _package = {
15296
15198
  scripts: scripts
15297
15199
  };
15298
15200
 
15299
- let assetManager = new AssetManager();
15201
+ /**
15202
+ * @classdesc
15203
+ * An Asset Manager class to load spine assets
15204
+ */
15205
+ class AssetManager {
15206
+ asset_manager;
15207
+ pathPrefix;
15208
+
15209
+ /**
15210
+ * @param {CanvasRenderer|WebGLRenderer} renderer - a melonJS renderer instance
15211
+ * @param {string} [pathPrefix=""] - a default path prefix for assets location
15212
+ */
15213
+ constructor(renderer, pathPrefix = "") {
15214
+ this.pathPrefix = pathPrefix;
15215
+ if (renderer.WebGLVersion >= 1) {
15216
+ this.asset_manager = new AssetManager$2(renderer.getContext(), this.pathPrefix);
15217
+ } else {
15218
+ // canvas renderer
15219
+ this.asset_manager = new AssetManager$1(this.pathPrefix);
15220
+ }
15221
+
15222
+ // set the spine custom parser
15223
+ loader.setParser("spine", (data, onload, onerror) => {
15224
+ // decompose data.src for the spine loader
15225
+ const ext = utils.file.getExtension(data.src);
15226
+ const basename = utils.file.getBasename(data.src);
15227
+ const path = utils.file.getPath(data.src);
15228
+ const filename = basename + "." + ext;
15229
+
15230
+ this.setPrefix(path);
15231
+
15232
+ // load asset
15233
+ switch (ext) {
15234
+ case "atlas":
15235
+ this.loadTextureAtlas(filename, onload, onerror);
15236
+ break;
15237
+ case "json":
15238
+ this.loadText(filename, onload, onerror);
15239
+ break;
15240
+ case "skel":
15241
+ this.loadBinary(filename, onload, onerror);
15242
+ break;
15243
+ default:
15244
+ throw "Spine plugin: unknown extension when preloading spine assets";
15245
+ }
15246
+
15247
+ return 1;
15248
+ });
15249
+
15250
+ }
15251
+
15252
+ /**
15253
+ * set a default path prefix for assets location
15254
+ * @see loadAsset
15255
+ * @param {string} pathPrefix
15256
+ */
15257
+ setPrefix(pathPrefix) {
15258
+ this.asset_manager.pathPrefix = this.pathPrefix = pathPrefix;
15259
+ }
15260
+
15261
+ /**
15262
+ * define all spine assets to be loaded
15263
+ * @see setPrefix
15264
+ * @see loadAll
15265
+ * @param {string} atlas
15266
+ * @param {string} skel
15267
+ * @example
15268
+ * // "manually" load spine assets
15269
+ * Spine.assetManager.setPrefix("data/spine/");
15270
+ * Spine.assetManager.loadAsset("alien.atlas", "alien-ess.json");
15271
+ * await Spine.assetManager.loadAll();
15272
+ */
15273
+ loadAsset(atlas, skel) {
15274
+ if (atlas) {
15275
+ this.loadTextureAtlas(atlas);
15276
+ }
15277
+
15278
+ if (skel.endsWith(".skel")) {
15279
+ this.loadBinary(skel);
15280
+ } else {
15281
+ this.loadText(skel);
15282
+ }
15283
+ }
15284
+
15285
+ /**
15286
+ * load the given texture atlas
15287
+ * @param {string} atlas
15288
+ */
15289
+ loadTextureAtlas(atlas, onload, onerror) {
15290
+ return this.asset_manager.loadTextureAtlas(atlas, onload, onerror);
15291
+ }
15292
+
15293
+
15294
+ /**
15295
+ * load the given skeleton .skel file
15296
+ * @param {string} skel
15297
+ */
15298
+ loadBinary(skel, onload, onerror) {
15299
+ return this.asset_manager.loadBinary(skel, onload, onerror);
15300
+ }
15301
+
15302
+ /**
15303
+ * load the given skeleton binary file
15304
+ * @param {string} skel
15305
+ */
15306
+ loadText(skel, onload, onerror) {
15307
+ return this.asset_manager.loadText(skel, onload, onerror);
15308
+ }
15309
+
15310
+ /**
15311
+ * load all defined spine assets
15312
+ * @see loadAsset
15313
+ */
15314
+ loadAll() {
15315
+ return this.asset_manager.loadAll();
15316
+ }
15317
+
15318
+ /**
15319
+ * get the loaded skeleton data
15320
+ * @param {string} path
15321
+ */
15322
+ require(path) {
15323
+ return this.asset_manager.require(path);
15324
+ }
15325
+ }
15300
15326
 
15301
- // a custom Spine parser for melonJS preloader
15302
- function spineParser(data, onload, onerror) {
15327
+ /**
15328
+ * @classdesc
15329
+ * a Spine 4.x plugin implementation for melonJS
15330
+ * @augments plugin.BasePlugin
15331
+ */
15332
+ class SpinePlugin extends plugin.BasePlugin {
15333
+ constructor() {
15334
+ // call the super constructor
15335
+ super();
15303
15336
 
15304
- // decompose data.src for the spine loader
15305
- const ext = utils.file.getExtension(data.src);
15306
- const basename = utils.file.getBasename(data.src);
15307
- const path = utils.file.getPath(data.src);
15308
- const filename = basename + "." + ext;
15337
+ // minimum melonJS version expected to run this plugin
15338
+ this.version = peerDependencies["melonjs"];
15309
15339
 
15310
- // set url prefix
15311
- assetManager.setPrefix(path);
15340
+ // hello world
15341
+ console.log(`${name} ${version} - spine runtime ${dependencies["@esotericsoftware/spine-core"]} | ${homepage}`);
15312
15342
 
15313
- // load asset
15314
- switch (ext) {
15315
- case "atlas":
15316
- assetManager.asset_manager.loadTextureAtlas(filename, onload, onerror);
15317
- break;
15318
- case "json":
15319
- assetManager.asset_manager.loadText(filename, onload, onerror);
15320
- break;
15321
- case "skel":
15322
- assetManager.asset_manager.loadBinary(filename, onload, onerror);
15323
- break;
15324
- default:
15325
- throw "Spine plugin: unknown extension when preloading spine assets";
15343
+ // instantiate the asset manager
15344
+ this.assetManager = new AssetManager(this.app.renderer);
15326
15345
  }
15327
-
15328
- return 1;
15329
15346
  }
15330
15347
 
15331
- // set the spine custom parser
15332
- loader.setParser("spine", spineParser);
15333
-
15334
- // hello world
15335
- event.once(event.VIDEO_INIT, () => {
15336
- console.log(`${name} ${version} - spine runtime ${dependencies["@esotericsoftware/spine-core"]} | ${homepage}`);
15337
- });
15348
+ // a temporary array used for skeleton.getBounds();
15349
+ let tempArray = [];
15338
15350
 
15339
15351
  /**
15340
15352
  * @classdesc
15341
- * An object to display a Spine animated skeleton on screen.
15353
+ * An renderable object to render Spine animated skeleton.
15342
15354
  * @augments Renderable
15343
15355
  */
15344
15356
  class Spine extends Renderable$1 {
15345
15357
  runtime;
15346
15358
  skeleton;
15359
+ plugin;
15360
+ renderer;
15347
15361
  animationState;
15348
15362
  skeletonRenderer;
15349
- assetManager;
15350
15363
  root;
15351
15364
  boneOffset;
15352
15365
  boneSize;
15366
+ isSpineFlipped = {
15367
+ x : false,
15368
+ y : false
15369
+ };
15370
+
15371
+ /**
15372
+ * Stores settings and other state for the playback of the current animation (if any).
15373
+ * @type {TrackEntry}
15374
+ * @see http://en.esotericsoftware.com/spine-api-reference#TrackEntry
15375
+ * @see setAnimation
15376
+ * @default undefined
15377
+ * @example
15378
+ * // set a default animation to "run"
15379
+ * this.setAnimation(0, "run", true);
15380
+ * ...
15381
+ * ...
15382
+ * // pause the animation
15383
+ * this.currentTrack.timeScale = 0;
15384
+ * ...
15385
+ * ...
15386
+ * // resume the animation
15387
+ * this.currentTrack.timeScale = 1;
15388
+ */
15389
+ currentTrack;
15353
15390
 
15354
15391
  /**
15355
15392
  * @param {number} x - the x coordinates of the Spine object
@@ -15388,13 +15425,19 @@ class Spine extends Renderable$1 {
15388
15425
  constructor(x, y, settings) {
15389
15426
  super(x, y, settings.width, settings.height);
15390
15427
 
15391
- if (video.renderer.WebGLVersion >= 1) {
15428
+ // ensure plugin was properly registered
15429
+ this.plugin = plugin.get(SpinePlugin);
15430
+ if (typeof this.plugin === "undefined") {
15431
+ throw "Spine plugin: plugin needs to be registered first using plugin.register";
15432
+ }
15433
+ this.renderer = this.plugin.app.renderer;
15434
+
15435
+ if (this.renderer.WebGLVersion >= 1) {
15392
15436
  this.runtime = spineWebGL;
15393
15437
  } else {
15394
15438
  this.runtime = spineCanvas;
15395
15439
  }
15396
15440
 
15397
- this.assetManager = assetManager.asset_manager;
15398
15441
  this.skeletonRenderer = new SkeletonRenderer(this.runtime);
15399
15442
 
15400
15443
  // force anchorPoint to 0,0
@@ -15453,15 +15496,15 @@ class Spine extends Renderable$1 {
15453
15496
  */
15454
15497
  setSkeleton(atlasFile, jsonFile) {
15455
15498
  // Create the texture atlas and skeleton data.
15456
- let atlas = this.assetManager.require(atlasFile);
15499
+ let atlas = this.plugin.assetManager.require(atlasFile);
15457
15500
  let atlasLoader = new this.runtime.AtlasAttachmentLoader(atlas);
15458
15501
  let skeletonJson = new this.runtime.SkeletonJson(atlasLoader);
15459
- let skeletonData = skeletonJson.readSkeletonData(this.assetManager.require(jsonFile));
15502
+ let skeletonData = skeletonJson.readSkeletonData(this.plugin.assetManager.require(jsonFile));
15460
15503
 
15461
15504
  // Instantiate a new skeleton based on the atlas and skeleton data.
15462
15505
  this.skeleton = new this.runtime.Skeleton(skeletonData);
15463
- this.skeleton.setToSetupPose();
15464
- this.skeleton.updateWorldTransform();
15506
+
15507
+ this.setToSetupPose();
15465
15508
 
15466
15509
  // Setup an animation state with a default mix of 0.2 seconds.
15467
15510
  var animationStateData = new this.runtime.AnimationStateData(this.skeleton.data);
@@ -15470,11 +15513,34 @@ class Spine extends Renderable$1 {
15470
15513
 
15471
15514
  // get a reference to the root bone
15472
15515
  this.root = this.skeleton.getRootBone();
15473
- // Spine uses Y-up, melonJS uses Y-down
15474
- this.root.scaleY *= -1;
15516
+ }
15475
15517
 
15476
- // mark the object as dirty
15477
- this.isDirty = true;
15518
+ /**
15519
+ * flip the Spine skeleton on the horizontal axis (around its center)
15520
+ * @param {boolean} [flip=true] - `true` to flip this Spine object.
15521
+ * @returns {Spine} Reference to this object for method chaining
15522
+ */
15523
+ flipX(flip = true) {
15524
+ if (this.isSpineFlipped.x !== flip) {
15525
+ this.isSpineFlipped.x = flip;
15526
+ this.root.scaleX *= -1;
15527
+ this.isDirty = true;
15528
+ }
15529
+ return this;
15530
+ }
15531
+
15532
+ /**
15533
+ * flip the Spine skeleton on the vertical axis (around its center)
15534
+ * @param {boolean} [flip=true] - `true` to flip this Spine object.
15535
+ * @returns {Spine} Reference to this object for method chaining
15536
+ */
15537
+ flipY(flip = true) {
15538
+ if (this.isSpineFlipped.y !== flip) {
15539
+ this.isSpineFlipped.y = flip;
15540
+ this.root.scaleY *= -1;
15541
+ this.isDirty = true;
15542
+ }
15543
+ return this;
15478
15544
  }
15479
15545
 
15480
15546
  /**
@@ -15523,13 +15589,16 @@ class Spine extends Renderable$1 {
15523
15589
  let boneOffset = this.boneOffset;
15524
15590
  let boneSize = this.boneSize;
15525
15591
 
15526
- this.skeleton.getBounds(boneOffset, boneSize);
15592
+ this.skeleton.getBounds(boneOffset, boneSize, tempArray);
15593
+
15594
+ let minX = boneOffset.x - rootBone.x,
15595
+ minY = boneOffset.y - rootBone.y;
15527
15596
 
15528
15597
  bounds.addFrame(
15529
- boneOffset.x - rootBone.x,
15530
- boneOffset.y - rootBone.y,
15531
- boneSize.x + boneOffset.x - rootBone.x,
15532
- boneSize.y + boneOffset.y - rootBone.y,
15598
+ minX,
15599
+ minY,
15600
+ minX + boneSize.x,
15601
+ minY + boneSize.y,
15533
15602
  !isIdentity ? this.currentTransform : undefined
15534
15603
  );
15535
15604
  } else {
@@ -15544,6 +15613,7 @@ class Spine extends Renderable$1 {
15544
15613
 
15545
15614
  if (absolute === true) {
15546
15615
  var absPos = this.getAbsolutePosition();
15616
+ //bounds.translate(absPos.x, absPos.y);
15547
15617
  bounds.centerOn(absPos.x + bounds.centerX, absPos.y + bounds.centerY);
15548
15618
  }
15549
15619
  return bounds;
@@ -15563,22 +15633,24 @@ class Spine extends Renderable$1 {
15563
15633
  update(dt) {
15564
15634
  if (typeof this.skeleton !== "undefined") {
15565
15635
  let rootBone = this.skeleton.getRootBone();
15566
-
15567
- // update the root bone position
15568
- if (rootBone.x !== this.pos.x) {
15569
- rootBone.x = this.pos.x;
15570
- }
15571
- if (rootBone.y !== this.pos.y) {
15572
- rootBone.y = this.pos.y;
15573
- }
15636
+ //let height = this.renderer.getHeight();
15574
15637
 
15575
15638
  // Update and apply the animation state, update the skeleton's
15576
- // world transforms and render the skeleton.
15577
15639
  this.animationState.update(dt / 1000);
15578
15640
  this.animationState.apply(this.skeleton);
15641
+
15642
+ // update the root bone position
15643
+ rootBone.x = this.pos.x;
15644
+ rootBone.y = this.pos.y;
15645
+
15646
+ // world transforms
15579
15647
  this.skeleton.updateWorldTransform();
15580
15648
 
15649
+ // update Bounds
15581
15650
  this.updateBounds();
15651
+
15652
+ // world transforms
15653
+ //this.skeleton.updateWorldTransform();
15582
15654
  }
15583
15655
  return true;
15584
15656
  }
@@ -15598,13 +15670,13 @@ class Spine extends Renderable$1 {
15598
15670
  * @param {number} [track_index] - If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from). In either case trackEnd determines when the track is cleared.
15599
15671
  * @param {number} [index] - the animation index
15600
15672
  * @param {boolean} [loop= false] - If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its duration.
15601
- * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose event occurs.
15673
+ * @returns {TrackEntry} A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose event occurs.
15602
15674
  */
15603
15675
  setAnimationByIndex(track_index, index, loop = false) {
15604
15676
  if (index < 0 || index >= this.skeleton.data.animations.length) {
15605
15677
  return (console.log("Animation Index not found"));
15606
15678
  } else {
15607
- this.animationState.setAnimation(track_index, this.skeleton.data.animations[index].name, loop);
15679
+ return this.setAnimation(track_index, this.skeleton.data.animations[index].name, loop);
15608
15680
  }
15609
15681
  }
15610
15682
 
@@ -15613,25 +15685,40 @@ class Spine extends Renderable$1 {
15613
15685
  * @param {number} [track_index] - If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from). In either case trackEnd determines when the track is cleared.
15614
15686
  * @param {string} [name] - the animation name
15615
15687
  * @param {boolean} [loop= false] - If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its duration.
15616
- * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose event occurs.
15688
+ * @returns {TrackEntry} A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose event occurs.
15617
15689
  * @example
15618
15690
  * // set the current animation
15619
15691
  * spineAlien.setAnimation(0, "death", true);
15620
15692
  */
15621
15693
  setAnimation(track_index, name, loop = false) {
15622
- this.animationState.setAnimation(track_index, name, loop);
15694
+ this.currentTrack = this.animationState.setAnimation(track_index, name, loop);
15695
+ return this.currentTrack;
15696
+ }
15697
+
15698
+ /**
15699
+ * return true if the given animation name is the current running animation for the current track.
15700
+ * @name isCurrentAnimation
15701
+ * @param {string} name - animation name
15702
+ * @returns {boolean}
15703
+ * @example
15704
+ * if (!this.isCurrentAnimation("death")) {
15705
+ * // do something funny...
15706
+ * }
15707
+ */
15708
+ isCurrentAnimation(name) {
15709
+ return typeof this.currentTrack !== "undefined" && this.currentTrack.animation.name === name;
15623
15710
  }
15624
15711
 
15625
15712
  /**
15626
15713
  * Adds an animation to be played after the current or last queued animation for a track, and sets the track entry's mixDuration.
15627
15714
  * @param {number} [delay=0] - If > 0, sets delay. If <= 0, the delay set is the duration of the previous track entry minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next loop completion is used instead of its duration.
15628
- * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose} event occurs.
15715
+ * @return {TrackEntry} A track entry to allow further customization of animation playback. References to the track entry must not be kept after the dispose} event occurs.
15629
15716
  */
15630
15717
  addAnimationByIndex(track_index, index, loop = false, delay = 0) {
15631
15718
  if (index < 0 || index >= this.skeleton.data.animations.length) {
15632
15719
  return (console.log("Animation Index not found"));
15633
15720
  } else {
15634
- this.animationState.addAnimation(track_index, this.skeleton.data.animations[index].name, loop, delay);
15721
+ return this.addAnimation(track_index, this.skeleton.data.animations[index].name, loop, delay);
15635
15722
  }
15636
15723
  }
15637
15724
 
@@ -15691,11 +15778,21 @@ class Spine extends Renderable$1 {
15691
15778
  }
15692
15779
 
15693
15780
  /**
15694
- * Sets this slot to the setup pose.
15781
+ * Reset this slot to the setup pose.
15695
15782
  */
15696
15783
  setToSetupPose() {
15697
15784
  this.skeleton.setToSetupPose();
15785
+ // Spine uses Y-up, melonJS uses Y-down
15786
+ this.skeleton.getRootBone().scaleY *= -1;
15787
+ this.skeleton.updateWorldTransform();
15788
+ // reset flip flags
15789
+ this.isSpineFlipped.y = false;
15790
+ this.isSpineFlipped.x = false;
15791
+ // reset reference to current track entry
15792
+ this.currentTrack = undefined;
15793
+ // mark the object as dirty
15794
+ this.isDirty = true;
15698
15795
  }
15699
15796
  }
15700
15797
 
15701
- export { assetManager, Spine as default };
15798
+ export { SpinePlugin, Spine as default };