@melonjs/spine-plugin 1.3.0 → 1.4.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.3.0
2
+ * melonJS Spine plugin - v1.4.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, Renderable as Renderable$1, Vector2d } from 'melonjs';
8
+ import { event, video, Color as Color$1, Polygon, Math as Math$1, utils, loader, Renderable as Renderable$1, Vector2d } from 'melonjs';
9
9
 
10
10
  /******************************************************************************
11
11
  * Spine Runtimes License Agreement
@@ -11292,21 +11292,39 @@ class WebGLBlendModeConverter {
11292
11292
  default: throw new Error("Unknown blend mode: " + blendMode);
11293
11293
  }
11294
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
+ }
11295
11313
  static getSourceColorGLBlendMode(blendMode, premultipliedAlpha = false) {
11296
11314
  switch (blendMode) {
11297
11315
  case BlendMode.Normal: return premultipliedAlpha ? ONE : SRC_ALPHA;
11298
11316
  case BlendMode.Additive: return premultipliedAlpha ? ONE : SRC_ALPHA;
11299
11317
  case BlendMode.Multiply: return DST_COLOR;
11300
- case BlendMode.Screen: return ONE;
11318
+ case BlendMode.Screen: return premultipliedAlpha ? ONE : SRC_ALPHA;
11301
11319
  default: throw new Error("Unknown blend mode: " + blendMode);
11302
11320
  }
11303
11321
  }
11304
- static getSourceAlphaGLBlendMode(blendMode) {
11322
+ static getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha = false) {
11305
11323
  switch (blendMode) {
11306
- case BlendMode.Normal: return ONE;
11307
- case BlendMode.Additive: return ONE;
11308
- case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
11309
- case BlendMode.Screen: return ONE_MINUS_SRC_COLOR;
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;
11310
11328
  default: throw new Error("Unknown blend mode: " + blendMode);
11311
11329
  }
11312
11330
  }
@@ -12779,7 +12797,8 @@ class PolygonBatcher {
12779
12797
  let gl = this.context.gl;
12780
12798
  this.srcColorBlend = gl.SRC_ALPHA;
12781
12799
  this.srcAlphaBlend = gl.ONE;
12782
- this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
12800
+ this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA;
12801
+ this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA;
12783
12802
  }
12784
12803
  begin(shader) {
12785
12804
  if (this.isDrawing)
@@ -12790,23 +12809,24 @@ class PolygonBatcher {
12790
12809
  this.isDrawing = true;
12791
12810
  let gl = this.context.gl;
12792
12811
  gl.enable(gl.BLEND);
12793
- gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
12812
+ gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend);
12794
12813
  if (PolygonBatcher.disableCulling) {
12795
12814
  this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);
12796
12815
  if (this.cullWasEnabled)
12797
12816
  gl.disable(gl.CULL_FACE);
12798
12817
  }
12799
12818
  }
12800
- setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) {
12801
- if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend)
12819
+ setBlendMode(srcColorBlend, srcAlphaBlend, dstColorBlend, dstAlphaBlend) {
12820
+ if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstColorBlend == dstColorBlend && this.dstAlphaBlend == dstAlphaBlend)
12802
12821
  return;
12803
12822
  this.srcColorBlend = srcColorBlend;
12804
12823
  this.srcAlphaBlend = srcAlphaBlend;
12805
- this.dstBlend = dstBlend;
12824
+ this.dstColorBlend = dstColorBlend;
12825
+ this.dstAlphaBlend = dstAlphaBlend;
12806
12826
  if (this.isDrawing) {
12807
12827
  this.flush();
12808
12828
  let gl = this.context.gl;
12809
- gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
12829
+ gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend);
12810
12830
  }
12811
12831
  }
12812
12832
  draw(texture, vertices, indices) {
@@ -12917,7 +12937,8 @@ class ShapeRenderer {
12917
12937
  let gl = this.context.gl;
12918
12938
  this.srcColorBlend = gl.SRC_ALPHA;
12919
12939
  this.srcAlphaBlend = gl.ONE;
12920
- this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
12940
+ this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA;
12941
+ this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA;
12921
12942
  }
12922
12943
  begin(shader) {
12923
12944
  if (this.isDrawing)
@@ -12927,16 +12948,17 @@ class ShapeRenderer {
12927
12948
  this.isDrawing = true;
12928
12949
  let gl = this.context.gl;
12929
12950
  gl.enable(gl.BLEND);
12930
- gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
12951
+ gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend);
12931
12952
  }
12932
- setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) {
12953
+ setBlendMode(srcColorBlend, srcAlphaBlend, dstColorBlend, dstAlphaBlend) {
12933
12954
  this.srcColorBlend = srcColorBlend;
12934
12955
  this.srcAlphaBlend = srcAlphaBlend;
12935
- this.dstBlend = dstBlend;
12956
+ this.dstColorBlend = dstColorBlend;
12957
+ this.dstAlphaBlend = dstAlphaBlend;
12936
12958
  if (this.isDrawing) {
12937
12959
  this.flush();
12938
12960
  let gl = this.context.gl;
12939
- gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
12961
+ gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend);
12940
12962
  }
12941
12963
  }
12942
12964
  setColor(color) {
@@ -13271,7 +13293,7 @@ class SkeletonDebugRenderer {
13271
13293
  let skeletonY = skeleton.y;
13272
13294
  let gl = this.context.gl;
13273
13295
  let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;
13274
- shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
13296
+ shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
13275
13297
  let bones = skeleton.bones;
13276
13298
  if (this.drawBones) {
13277
13299
  shapes.setColor(this.boneLineColor);
@@ -13589,7 +13611,7 @@ let SkeletonRenderer$2 = class SkeletonRenderer {
13589
13611
  let slotBlendMode = slot.data.blendMode;
13590
13612
  if (slotBlendMode != blendMode) {
13591
13613
  blendMode = slotBlendMode;
13592
- batcher.setBlendMode(WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode), WebGLBlendModeConverter.getDestGLBlendMode(blendMode));
13614
+ batcher.setBlendMode(WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getDestColorGLBlendMode(blendMode), WebGLBlendModeConverter.getDestAlphaGLBlendMode(blendMode, premultipliedAlpha));
13593
13615
  }
13594
13616
  if (clipper.isClipping()) {
13595
13617
  clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
@@ -14185,7 +14207,7 @@ class LoadingScreen {
14185
14207
  let gl = renderer.context.gl;
14186
14208
  renderer.resize(ResizeMode.Expand);
14187
14209
  renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);
14188
- renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
14210
+ renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
14189
14211
  if (complete) {
14190
14212
  this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);
14191
14213
  if (this.fadeOut > FADE_OUT)
@@ -14890,28 +14912,50 @@ var spineCanvas = {
14890
14912
  WindowedMean: WindowedMean
14891
14913
  };
14892
14914
 
14915
+ /**
14916
+ * @classdesc
14917
+ * An Asset Manager class to load spine assets
14918
+ */
14893
14919
  class AssetManager {
14894
14920
  asset_manager;
14895
14921
  pathPrefix;
14896
14922
 
14923
+ /**
14924
+ * @param {string} [pathPrefix=""] - a default path prefix for assets location
14925
+ */
14897
14926
  constructor(pathPrefix = "") {
14898
- event.once(event.VIDEO_INIT, this.initAssetManager.bind(this));
14899
- this.pathPrefix = pathPrefix;
14900
- }
14901
-
14902
- initAssetManager() {
14903
- if (video.renderer.WebGLVersion >= 1) {
14904
- this.asset_manager = new AssetManager$2(video.renderer.getContext(), this.pathPrefix);
14905
- } else {
14906
- // canvas renderer
14907
- this.asset_manager = new AssetManager$1(this.pathPrefix);
14908
- }
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
+ });
14909
14936
  }
14910
14937
 
14938
+ /**
14939
+ * set a default path prefix for assets location
14940
+ * @see loadAsset
14941
+ * @param {string} pathPrefix
14942
+ */
14911
14943
  setPrefix(pathPrefix) {
14912
- this.asset_manager.pathPrefix = pathPrefix;
14944
+ this.asset_manager.pathPrefix = this.pathPrefix = pathPrefix;
14913
14945
  }
14914
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
+ */
14915
14959
  loadAsset(atlas, skel) {
14916
14960
  if (atlas) {
14917
14961
  this.asset_manager.loadTextureAtlas(atlas);
@@ -14924,6 +14968,10 @@ class AssetManager {
14924
14968
  }
14925
14969
  }
14926
14970
 
14971
+ /**
14972
+ * load all defined spine assets
14973
+ * @see loadAsset
14974
+ */
14927
14975
  loadAll() {
14928
14976
  return this.asset_manager.loadAll();
14929
14977
  }
@@ -15147,8 +15195,152 @@ class SkeletonRenderer {
15147
15195
  }
15148
15196
  }
15149
15197
 
15198
+ var name = "@melonjs/spine-plugin";
15199
+ var version = "1.4.0";
15200
+ var description = "melonJS Spine plugin";
15201
+ var homepage = "https://github.com/melonjs/spine-plugin#readme";
15202
+ var type = "module";
15203
+ var keywords = [
15204
+ "2D",
15205
+ "HTML5",
15206
+ "javascript",
15207
+ "TypeScript",
15208
+ "ES6",
15209
+ "Canvas",
15210
+ "WebGL",
15211
+ "WebGL2",
15212
+ "melonjs",
15213
+ "plugin",
15214
+ "spine",
15215
+ "spine-runtimes",
15216
+ "spine-animation",
15217
+ "esotericsoftware"
15218
+ ];
15219
+ var repository = {
15220
+ type: "git",
15221
+ url: "git+https://github.com/melonjs/spine-plugin.git"
15222
+ };
15223
+ var bugs = {
15224
+ url: "https://github.com/melonjs/spine-plugin/issues"
15225
+ };
15226
+ var license = "MIT";
15227
+ var author = "AltByte Pte Ltd";
15228
+ var funding = "https://github.com/sponsors/melonjs";
15229
+ var engines = {
15230
+ node: ">= 19"
15231
+ };
15232
+ var main = "dist/@melonjs/spine-plugin.js";
15233
+ var module = "dist/@melonjs/spine-plugin.js";
15234
+ var types = "dist/@melonjs/spine-plugin.d.ts";
15235
+ var sideEffects = false;
15236
+ var files = [
15237
+ "dist/",
15238
+ "src/",
15239
+ "package.json",
15240
+ "README.md",
15241
+ "LICENSE",
15242
+ "CHANGELOG.md"
15243
+ ];
15244
+ var peerDependencies = {
15245
+ melonjs: "^15.10.0"
15246
+ };
15247
+ var dependencies = {
15248
+ "@esotericsoftware/spine-canvas": "^4.2.19",
15249
+ "@esotericsoftware/spine-core": "^4.2.19",
15250
+ "@esotericsoftware/spine-webgl": "^4.2.19"
15251
+ };
15252
+ var devDependencies = {
15253
+ "@babel/eslint-parser": "^7.22.15",
15254
+ "@babel/plugin-syntax-import-assertions": "^7.22.5",
15255
+ "@rollup/plugin-commonjs": "^25.0.4",
15256
+ "@rollup/plugin-json": "^6.0.0",
15257
+ "@rollup/plugin-node-resolve": "^15.2.1",
15258
+ "@rollup/plugin-replace": "^5.0.2",
15259
+ "del-cli": "^5.1.0",
15260
+ eslint: "^8.48.0",
15261
+ "eslint-plugin-jsdoc": "^46.5.1",
15262
+ rollup: "^3.28.1",
15263
+ "rollup-plugin-bundle-size": "^1.0.3",
15264
+ typescript: "^5.2.2"
15265
+ };
15266
+ var scripts = {
15267
+ build: "npm run clean && npm run lint && rollup -c --silent && npm run types",
15268
+ lint: "eslint src/**.js rollup.config.mjs",
15269
+ serve: "python3 -m http.server",
15270
+ test: "npm run serve",
15271
+ prepublishOnly: "npm run build",
15272
+ clean: "del-cli --force dist/*",
15273
+ types: "tsc"
15274
+ };
15275
+ var _package = {
15276
+ name: name,
15277
+ version: version,
15278
+ description: description,
15279
+ homepage: homepage,
15280
+ type: type,
15281
+ keywords: keywords,
15282
+ repository: repository,
15283
+ bugs: bugs,
15284
+ license: license,
15285
+ author: author,
15286
+ funding: funding,
15287
+ engines: engines,
15288
+ main: main,
15289
+ module: module,
15290
+ types: types,
15291
+ sideEffects: sideEffects,
15292
+ files: files,
15293
+ peerDependencies: peerDependencies,
15294
+ dependencies: dependencies,
15295
+ devDependencies: devDependencies,
15296
+ scripts: scripts
15297
+ };
15298
+
15150
15299
  let assetManager = new AssetManager();
15151
15300
 
15301
+ // a custom Spine parser for melonJS preloader
15302
+ function spineParser(data, onload, onerror) {
15303
+
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;
15309
+
15310
+ // set url prefix
15311
+ assetManager.setPrefix(path);
15312
+
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";
15326
+ }
15327
+
15328
+ return 1;
15329
+ }
15330
+
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
+ });
15338
+
15339
+ /**
15340
+ * @classdesc
15341
+ * An object to display a Spine animated skeleton on screen.
15342
+ * @augments Renderable
15343
+ */
15152
15344
  class Spine extends Renderable$1 {
15153
15345
  runtime;
15154
15346
  skeleton;
@@ -15159,6 +15351,40 @@ class Spine extends Renderable$1 {
15159
15351
  boneOffset;
15160
15352
  boneSize;
15161
15353
 
15354
+ /**
15355
+ * @param {number} x - the x coordinates of the Spine object
15356
+ * @param {number} y - the y coordinates of the Spine object
15357
+ * @param {object} settings - Configuration parameters for the Spine object
15358
+ * @param {number} [settings.atlasFile] - the name of the atlasFile to be used to create this spine animation
15359
+ * @param {number} [settings.jsonFile] - the name of the atlasFile to be used to create this spine animation
15360
+ * @param {number} [settings.mixTime = 0.2] - the default mix duration to use when no mix duration has been defined between two animations.
15361
+ * @example
15362
+ * import * as Spine from '@melonjs/spine-plugin';
15363
+ * import * as me from 'melonjs';
15364
+ *
15365
+ * // prepare/declare assets for the preloader
15366
+ * const DataManifest = [
15367
+ * {
15368
+ * "name": "alien-ess.json",
15369
+ * "type": "spine",
15370
+ * "src": "data/spine/alien-ess.json"
15371
+ * },
15372
+ * {
15373
+ * "name": "alien.atlas",
15374
+ * "type": "spine",
15375
+ * "src": "data/spine/alien.atlas"
15376
+ * },
15377
+ * ]
15378
+ *
15379
+ * // create a new Spine Renderable
15380
+ * let spineAlien = new Spine(100, 100, {atlasFile: "alien.atlas", jsonFile: "alien-ess.json"});
15381
+ *
15382
+ * // set default animation
15383
+ * spineAlien.setAnimation(0, "death", true);
15384
+ *
15385
+ * // add it to the game world
15386
+ * me.game.world.addChild(spineAlien);
15387
+ */
15162
15388
  constructor(x, y, settings) {
15163
15389
  super(x, y, settings.width, settings.height);
15164
15390
 
@@ -15179,20 +15405,26 @@ class Spine extends Renderable$1 {
15179
15405
  this.pos.z = settings.z;
15180
15406
  }
15181
15407
 
15182
- this.scaleValue = {x: 1, y: 1};
15408
+ // use internally when calulcating bounds
15183
15409
  this.boneOffset = new Vector2();
15184
15410
  this.boneSize = new Vector2();
15185
15411
 
15186
- this.mixTime = settings.mixTime || 0.2;
15412
+ // default mixTime
15413
+ this.mixTime = typeof settings.mixTime !== "undefined" ? settings.mixTime : 0.2;
15414
+
15187
15415
 
15188
15416
  if (settings.jsonFile) {
15189
15417
  this.jsonFile = settings.jsonFile;
15190
15418
  this.atlasFile = settings.atlasFile;
15191
-
15192
15419
  this.setSkeleton(this.atlasFile, this.jsonFile);
15193
15420
  }
15194
15421
  }
15195
15422
 
15423
+ /**
15424
+ * Whether to enabler the debug mode when rendering the spine object
15425
+ * @default false
15426
+ * @type {boolean}
15427
+ */
15196
15428
  get debugRendering() {
15197
15429
  return this.skeletonRenderer.debugRendering;
15198
15430
  }
@@ -15201,14 +15433,25 @@ class Spine extends Renderable$1 {
15201
15433
  this.skeletonRenderer.debugRendering = value;
15202
15434
  }
15203
15435
 
15436
+ /**
15437
+ * set and load the given skeleton atlas and json definition files
15438
+ * (use this if you did not specify any json or atlas through the constructor)
15439
+ * @param {number} [atlasFile] - the name of the atlasFile to be used to create this spine animation
15440
+ * @param {number} [jsonFile] - the name of the atlasFile to be used to create this spine animation
15441
+ * @example
15442
+ * // create a new Spine Renderable
15443
+ * let spineAlien = new Spine(100, 100);
15444
+ *
15445
+ * // set the skeleton
15446
+ * spineAlien.setSkeleton("alien.atlas", "alien-ess.json");
15447
+ *
15448
+ * // set default animation
15449
+ * spineAlien.setAnimation(0, "death", true);
15450
+ *
15451
+ * // add it to the game world
15452
+ * me.game.world.addChild(spineAlien);
15453
+ */
15204
15454
  setSkeleton(atlasFile, jsonFile) {
15205
- this.loadSpineAssets(atlasFile, jsonFile);
15206
- this.root = this.skeleton.getRootBone();
15207
- // Spine uses Y-up, melonJS uses Y-down
15208
- this.root.scaleY *= -1;
15209
- }
15210
-
15211
- loadSpineAssets(atlasFile, jsonFile) {
15212
15455
  // Create the texture atlas and skeleton data.
15213
15456
  let atlas = this.assetManager.require(atlasFile);
15214
15457
  let atlasLoader = new this.runtime.AtlasAttachmentLoader(atlas);
@@ -15224,20 +15467,50 @@ class Spine extends Renderable$1 {
15224
15467
  var animationStateData = new this.runtime.AnimationStateData(this.skeleton.data);
15225
15468
  animationStateData.defaultMix = this.mixTime;
15226
15469
  this.animationState = new this.runtime.AnimationState(animationStateData);
15470
+
15471
+ // get a reference to the root bone
15472
+ this.root = this.skeleton.getRootBone();
15473
+ // Spine uses Y-up, melonJS uses Y-down
15474
+ this.root.scaleY *= -1;
15475
+
15476
+ // mark the object as dirty
15477
+ this.isDirty = true;
15227
15478
  }
15228
15479
 
15480
+ /**
15481
+ * Rotate this Spine object by the specified angle (in radians).
15482
+ * @param {number} angle - The angle to rotate (in radians)
15483
+ * @param {Vector2d|ObservableVector2d} [v] - an optional point to rotate around
15484
+ * @returns {Spine} Reference to this object for method chaining
15485
+ */
15229
15486
  rotate(angle, v) {
15230
15487
  // rotation for rootBone is in degrees (anti-clockwise)
15231
15488
  this.skeleton.getRootBone().rotation -= Math$1.radToDeg(angle) + 90;
15232
15489
  // melonJS rotate method takes radians
15233
- super.rotate(angle, v);
15490
+ return super.rotate(angle, v);
15234
15491
  }
15235
15492
 
15493
+ /**
15494
+ * scale the Spine object around his anchor point. Scaling actually applies changes
15495
+ * to the currentTransform member wich is used by the renderer to scale the object
15496
+ * when rendering. It does not scale the object itself. For example if the renderable
15497
+ * is an image, the image.width and image.height properties are unaltered but the currentTransform
15498
+ * member will be changed.
15499
+ * @param {number} x - a number representing the abscissa of the scaling vector.
15500
+ * @param {number} [y=x] - a number representing the ordinate of the scaling vector.
15501
+ * @returns {Spine} Reference to this object for method chaining
15502
+ */
15236
15503
  scale(x, y = x) {
15237
- this.scaleValue = {x, y};
15238
- super.scale(x, y);
15504
+ // untested
15505
+ return super.scale(x, y);
15239
15506
  }
15240
15507
 
15508
+ /**
15509
+ * update the bounding box for this spine object.
15510
+ * (this will automatically update the bounds of the entire skeleton animation)
15511
+ * @param {boolean} [absolute=true] - update the bounds size and position in (world) absolute coordinates
15512
+ * @returns {Bounds} this shape bounding box Rectangle object
15513
+ */
15241
15514
  updateBounds(absolute = true) {
15242
15515
  if (this.isRenderable) {
15243
15516
  let bounds = this.getBounds();
@@ -15313,9 +15586,6 @@ class Spine extends Renderable$1 {
15313
15586
 
15314
15587
  /**
15315
15588
  * draw this spine object
15316
- * @name draw
15317
- * @memberof Spine
15318
- * @protected
15319
15589
  * @param {CanvasRenderer|WebGLRenderer} renderer - a renderer instance
15320
15590
  * @param {Camera2d} [viewport] - the viewport to (re)draw
15321
15591
  */
@@ -15323,6 +15593,13 @@ class Spine extends Renderable$1 {
15323
15593
  this.skeletonRenderer.draw(renderer, this.skeleton);
15324
15594
  }
15325
15595
 
15596
+ /**
15597
+ * Sets the current animation for a track, discarding any queued animations.
15598
+ * @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
+ * @param {number} [index] - the animation index
15600
+ * @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.
15602
+ */
15326
15603
  setAnimationByIndex(track_index, index, loop = false) {
15327
15604
  if (index < 0 || index >= this.skeleton.data.animations.length) {
15328
15605
  return (console.log("Animation Index not found"));
@@ -15331,10 +15608,25 @@ class Spine extends Renderable$1 {
15331
15608
  }
15332
15609
  }
15333
15610
 
15611
+ /**
15612
+ * Sets the current animation for a track, discarding any queued animations.
15613
+ * @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
+ * @param {string} [name] - the animation name
15615
+ * @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.
15617
+ * @example
15618
+ * // set the current animation
15619
+ * spineAlien.setAnimation(0, "death", true);
15620
+ */
15334
15621
  setAnimation(track_index, name, loop = false) {
15335
15622
  this.animationState.setAnimation(track_index, name, loop);
15336
15623
  }
15337
15624
 
15625
+ /**
15626
+ * Adds an animation to be played after the current or last queued animation for a track, and sets the track entry's mixDuration.
15627
+ * @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.
15629
+ */
15338
15630
  addAnimationByIndex(track_index, index, loop = false, delay = 0) {
15339
15631
  if (index < 0 || index >= this.skeleton.data.animations.length) {
15340
15632
  return (console.log("Animation Index not found"));
@@ -15363,18 +15655,44 @@ class Spine extends Renderable$1 {
15363
15655
  };
15364
15656
  }
15365
15657
 
15658
+ /**
15659
+ * Set the default mix duration to use when no mix duration has been defined between two animations.
15660
+ * @param {number} mixTime
15661
+ */
15366
15662
  setDefaultMixTime(mixTime) {
15367
- this.animationState.data.defaultMix = mixTime;
15663
+ this.animationState.data.defaultMix = this.mixTime = mixTime;
15368
15664
  }
15369
15665
 
15666
+ /**
15667
+ * Sets a mix duration by animation name.
15668
+ */
15370
15669
  setTransitionMixTime(firstAnimation, secondAnimation, mixTime) {
15371
15670
  this.animationState.setMix(firstAnimation, secondAnimation, mixTime);
15372
15671
  }
15373
15672
 
15673
+ /**
15674
+ * Sets a skin by name.
15675
+ * @param {string} skinName
15676
+ * @example
15677
+ * // create a new Spine Renderable
15678
+ * let spineAlien = new Spine(100, 100, {atlasFile: "mix-and-match-pma.atlas", jsonFile: "mix-and-match-pro.json"});
15679
+ *
15680
+ * // set default animation
15681
+ * spineAlien.setAnimation(0, "dance", true);
15682
+ *
15683
+ * // set default skin
15684
+ * spineAlien.setSkinByName("full-skins/girl");
15685
+ *
15686
+ * // add it to the game world
15687
+ * me.game.world.addChild(spineAlien);
15688
+ */
15374
15689
  setSkinByName(skinName) {
15375
15690
  this.skeleton.setSkinByName(skinName);
15376
15691
  }
15377
15692
 
15693
+ /**
15694
+ * Sets this slot to the setup pose.
15695
+ */
15378
15696
  setToSetupPose() {
15379
15697
  this.skeleton.setToSetupPose();
15380
15698
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melonjs/spine-plugin",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "melonJS Spine plugin",
5
5
  "homepage": "https://github.com/melonjs/spine-plugin#readme",
6
6
  "type": "module",
@@ -46,22 +46,23 @@
46
46
  "CHANGELOG.md"
47
47
  ],
48
48
  "peerDependencies": {
49
- "melonjs": "^15.9.2"
49
+ "melonjs": "^15.10.0"
50
50
  },
51
51
  "dependencies": {
52
- "@esotericsoftware/spine-canvas": "^4.2.18",
53
- "@esotericsoftware/spine-core": "^4.2.18",
54
- "@esotericsoftware/spine-webgl": "^4.2.18"
52
+ "@esotericsoftware/spine-canvas": "^4.2.19",
53
+ "@esotericsoftware/spine-core": "^4.2.19",
54
+ "@esotericsoftware/spine-webgl": "^4.2.19"
55
55
  },
56
56
  "devDependencies": {
57
- "@babel/eslint-parser": "^7.22.11",
57
+ "@babel/eslint-parser": "^7.22.15",
58
58
  "@babel/plugin-syntax-import-assertions": "^7.22.5",
59
59
  "@rollup/plugin-commonjs": "^25.0.4",
60
+ "@rollup/plugin-json": "^6.0.0",
60
61
  "@rollup/plugin-node-resolve": "^15.2.1",
61
62
  "@rollup/plugin-replace": "^5.0.2",
62
- "del-cli": "^5.0.1",
63
+ "del-cli": "^5.1.0",
63
64
  "eslint": "^8.48.0",
64
- "eslint-plugin-jsdoc": "^46.5.0",
65
+ "eslint-plugin-jsdoc": "^46.5.1",
65
66
  "rollup": "^3.28.1",
66
67
  "rollup-plugin-bundle-size": "^1.0.3",
67
68
  "typescript": "^5.2.2"