@melonjs/spine-plugin 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## 1.2.1 - _2023-08-23
4
+
5
+ - code refactoring and optimization to prepare for future feature additions
6
+ - fix URLs in the package.json file
7
+
8
+ ## 1.2.0 - _2023-08-22
9
+
10
+ - add support for clipping (coin example is now rendered properly)
11
+
12
+ ## 1.1.0 - _2023-08-19
13
+
14
+ - add some basic debug rendering
15
+ - optimize code (remove unneeded logic)
16
+
17
+ ## 1.0.0 - _2023-08-16_
18
+
19
+ initial release
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # melonJS Spine Plugin
2
2
 
3
- a [Spine](http://en.esotericsoftware.com/spine-in-depth) 4.1 plugin implementation for [melonJS 2](www.melonjs.org)
3
+ a [Spine](http://en.esotericsoftware.com/spine-in-depth) 4.1 plugin implementation for [melonJS 2](http://www.melonjs.org)
4
4
 
5
- ![melonjs-spine-gif](https://github.com/melonjs/spine-plugin/assets/4033090/e4f1db3e-e2c7-4d18-9d80-b42fc9897c59)
5
+ ![melonjs-spine-gif](https://github.com/melonjs/spine-plugin/assets/4033090/dc259c8e-def6-419e-83a9-cda374715686)
6
6
 
7
7
  >Note: although functional, this plugin is still a work in progress. Feedback and especially contributions are welcome!
8
8
 
@@ -17,6 +17,7 @@ this plugin is already bundled with the required Spine runtime, so there is no n
17
17
  >Note: this plugin requires melonJS version 15.9 or higher.
18
18
 
19
19
  To install the plugin using npm :
20
+
20
21
  `$ [sudo] npm install @melonjs/spine-plugin`
21
22
 
22
23
  Then import and use the plugin in your project. For example:
@@ -4070,12 +4070,14 @@ declare class CanvasTexture extends Texture {
4070
4070
  }
4071
4071
  declare class SkeletonRenderer {
4072
4072
  constructor(runtime: any);
4073
- isWebGLRenderer: any;
4074
4073
  skeletonRenderer: any;
4075
4074
  runtime: any;
4076
- tempColor: Color;
4077
4075
  tintColor: Color$1;
4076
+ vertexSize: number;
4078
4077
  debugRendering: boolean;
4078
+ clipper: SkeletonClipping;
4079
+ clippingVertices: any[];
4080
+ clippingMask: Polygon;
4079
4081
  draw(renderer: any, skeleton: any): void;
4080
4082
  }
4081
4083
  import { Vector2d } from 'melonjs';
@@ -4129,4 +4131,5 @@ declare class Vertices {
4129
4131
  vertices: any;
4130
4132
  }
4131
4133
  import { Color as Color$1 } from 'melonjs';
4134
+ import { Polygon } from 'melonjs';
4132
4135
  export { Spine as default };
@@ -1,11 +1,11 @@
1
1
  /*!
2
- * melonJS Spine plugin - v1.1.0
2
+ * melonJS Spine plugin - v1.2.1
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, Math as Math$1, Renderable as Renderable$1, Vector2d } from 'melonjs';
8
+ import { event, video, Color as Color$1, Polygon, Math as Math$1, Renderable as Renderable$1, Vector2d } from 'melonjs';
9
9
 
10
10
  /******************************************************************************
11
11
  * Spine Runtimes License Agreement
@@ -14932,40 +14932,77 @@ class AssetManager {
14932
14932
  const worldVertices = new Float32Array(8);
14933
14933
  const blendModeLUT = ["normal", "additive", "multiply", "screen"];
14934
14934
 
14935
+ const regionDebugColor = "green";
14936
+ const clipDebugColor = "blue";
14937
+
14935
14938
  class SkeletonRenderer {
14936
- isWebGLRenderer;
14937
14939
  skeletonRenderer;
14938
14940
  runtime;
14939
- tempColor = new Color();
14940
14941
  tintColor = new Color$1();
14942
+ vertexSize = 2 + 2 + 4;
14941
14943
  debugRendering = false;
14944
+ clipper = new SkeletonClipping();
14945
+ clippingVertices = [];
14946
+ clippingMask = new Polygon(0, 0);
14942
14947
 
14943
14948
  constructor(runtime) {
14944
14949
  this.runtime = runtime;
14945
14950
  this.skeletonRenderer = new runtime.SkeletonRenderer();
14946
- this.tempColor = new Color();
14947
14951
  }
14948
14952
 
14949
14953
  draw(renderer, skeleton) {
14950
- // based on https://github.com/EsotericSoftware/spine-runtimes/blob/4.1/spine-ts/spine-canvas/src/SkeletonRenderer.ts
14954
+ let clipper = this.clipper;
14951
14955
  let drawOrder = skeleton.drawOrder;
14952
14956
  let skeletonColor = skeleton.color;
14953
-
14954
- if (this.debugRendering === true) {
14955
- renderer.setColor("green");
14956
- }
14957
+ let clippingMask = this.clippingMask;
14958
+ let debugRendering = this.debugRendering;
14957
14959
 
14958
14960
  for (var i = 0, n = drawOrder.length; i < n; i++) {
14961
+ let clippedVertexSize = clipper.isClipping() ? 2 : this.vertexSize;
14959
14962
  let slot = drawOrder[i];
14960
14963
  let bone = slot.bone;
14964
+ let image;
14965
+ let region;
14961
14966
 
14962
- if (!bone.active) continue;
14967
+ if (!bone.active) {
14968
+ clipper.clipEndWithSlot(slot);
14969
+ renderer.clearMask();
14970
+ continue;
14971
+ }
14963
14972
 
14964
14973
  let attachment = slot.getAttachment();
14965
14974
 
14966
14975
  if (attachment instanceof RegionAttachment) {
14967
- let region = attachment.region;
14968
- let image = region.texture.getImage();
14976
+ attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
14977
+ region = attachment.region;
14978
+ image = region.texture.getImage();
14979
+ } else if (attachment instanceof MeshAttachment) {
14980
+ /*
14981
+ // commenting for now as totally untested
14982
+ let mesh = attachment;
14983
+ mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, worldVertices, 0, 2);
14984
+ region = mesh.region;
14985
+ image = mesh.region.texture.getImage();
14986
+ */
14987
+ console.warn("spine-plugin: MeshAttachment is not supported yet");
14988
+ } else if (attachment instanceof ClippingAttachment) {
14989
+ let clip = attachment;
14990
+ let vertices = this.clippingVertices;
14991
+ clipper.clipStart(slot, clip);
14992
+ clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
14993
+ clippingMask.setVertices(vertices, clip.worldVerticesLength);
14994
+ if (debugRendering === true) {
14995
+ renderer.setColor(clipDebugColor);
14996
+ renderer.stroke(clippingMask);
14997
+ }
14998
+ continue;
14999
+ } else {
15000
+ clipper.clipEndWithSlot(slot);
15001
+ renderer.clearMask();
15002
+ continue;
15003
+ }
15004
+
15005
+ if (typeof image !== "undefined") {
14969
15006
  let slotColor = slot.color;
14970
15007
  let regionColor = attachment.color;
14971
15008
  let blendMode = slot.data.blendMode;
@@ -14976,8 +15013,6 @@ class SkeletonRenderer {
14976
15013
  skeletonColor.b * slotColor.b * regionColor.b,
14977
15014
  skeletonColor.a * slotColor.a * regionColor.a);
14978
15015
 
14979
- attachment.computeWorldVertices(slot, worldVertices, 0, 2);
14980
-
14981
15016
  renderer.save();
14982
15017
  renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
14983
15018
  renderer.translate(attachment.offset[0], attachment.offset[1]);
@@ -15000,13 +15035,24 @@ class SkeletonRenderer {
15000
15035
  renderer.setTint(color);
15001
15036
  renderer.setBlendMode(blendModeLUT[blendMode]);
15002
15037
  renderer.setGlobalAlpha(color.a);
15038
+
15039
+ if (clipper.isClipping()) {
15040
+ renderer.setMask(clippingMask);
15041
+ }
15042
+
15003
15043
  renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
15004
- if (this.debugRendering === true) {
15044
+
15045
+ if (debugRendering === true) {
15046
+ renderer.setColor(regionDebugColor);
15005
15047
  renderer.strokeRect(0, 0, w, h);
15006
15048
  }
15049
+
15007
15050
  renderer.restore();
15008
15051
  }
15052
+ clipper.clipEndWithSlot(slot);
15053
+ renderer.clearMask();
15009
15054
  }
15055
+ clipper.clipEnd();
15010
15056
  }
15011
15057
  }
15012
15058
 
package/package.json CHANGED
@@ -1,27 +1,31 @@
1
1
  {
2
2
  "name": "@melonjs/spine-plugin",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "melonJS Spine plugin",
5
+ "homepage": "https://github.com/melonjs/spine-plugin#readme",
5
6
  "type": "module",
6
7
  "keywords": [
7
8
  "2D",
8
9
  "HTML5",
9
10
  "javascript",
10
11
  "TypeScript",
11
- "es6",
12
+ "ES6",
12
13
  "Canvas",
13
14
  "WebGL",
14
15
  "WebGL2",
15
16
  "melonjs",
16
- "Spine",
17
+ "plugin",
18
+ "spine",
19
+ "spine-runtimes",
20
+ "spine-animation",
17
21
  "esotericsoftware"
18
22
  ],
19
23
  "repository": {
20
24
  "type": "git",
21
- "url": "git+https://github.com/melonjs/debug-spine.git"
25
+ "url": "git+https://github.com/melonjs/spine-plugin.git"
22
26
  },
23
27
  "bugs": {
24
- "url": "https://github.com/melonjs/debug-spine/issues"
28
+ "url": "https://github.com/melonjs/spine-plugin/issues"
25
29
  },
26
30
  "license": "MIT",
27
31
  "author": "AltByte Pte Ltd",
@@ -38,7 +42,8 @@
38
42
  "src/",
39
43
  "package.json",
40
44
  "README.md",
41
- "LICENSE"
45
+ "LICENSE",
46
+ "CHANGELOG.md"
42
47
  ],
43
48
  "peerDependencies": {
44
49
  "melonjs": "^15.9.0"
@@ -52,12 +57,12 @@
52
57
  "@babel/eslint-parser": "^7.22.0",
53
58
  "@babel/plugin-syntax-import-assertions": "^7.22.5",
54
59
  "@rollup/plugin-commonjs": "^25.0.4",
55
- "@rollup/plugin-node-resolve": "^15.2.0",
60
+ "@rollup/plugin-node-resolve": "^15.2.1",
56
61
  "@rollup/plugin-replace": "^5.0.2",
57
62
  "del-cli": "^5.0.0",
58
63
  "eslint": "^8.47.0",
59
- "eslint-plugin-jsdoc": "^46.4.6",
60
- "rollup": "^3.28.0",
64
+ "eslint-plugin-jsdoc": "^46.5.0",
65
+ "rollup": "^3.28.1",
61
66
  "rollup-plugin-bundle-size": "^1.0.3",
62
67
  "typescript": "^5.1.6"
63
68
  },
@@ -69,9 +74,5 @@
69
74
  "prepublishOnly": "npm run build",
70
75
  "clean": "del-cli --force dist/*",
71
76
  "types": "tsc"
72
- },
73
- "homepage": "https://github.com/melonjs/spine-plugin#readme",
74
- "directories": {
75
- "test": "test"
76
77
  }
77
78
  }
@@ -1,43 +1,80 @@
1
- import { Color as MColor, Math as MMath } from "melonjs";
2
- import { RegionAttachment, Color } from "@esotericsoftware/spine-core";
1
+ import { Color as MColor, Math as MMath, Polygon } from "melonjs";
2
+ import { SkeletonClipping, ClippingAttachment, MeshAttachment, RegionAttachment } from "@esotericsoftware/spine-core";
3
3
 
4
4
  const worldVertices = new Float32Array(8);
5
5
  const blendModeLUT = ["normal", "additive", "multiply", "screen"];
6
6
 
7
+ const regionDebugColor = "green";
8
+ const clipDebugColor = "blue";
9
+
7
10
  export default class SkeletonRenderer {
8
- isWebGLRenderer;
9
11
  skeletonRenderer;
10
12
  runtime;
11
- tempColor = new Color();
12
13
  tintColor = new MColor();
14
+ vertexSize = 2 + 2 + 4;
13
15
  debugRendering = false;
16
+ clipper = new SkeletonClipping();
17
+ clippingVertices = [];
18
+ clippingMask = new Polygon(0, 0);
14
19
 
15
20
  constructor(runtime) {
16
21
  this.runtime = runtime;
17
22
  this.skeletonRenderer = new runtime.SkeletonRenderer();
18
- this.tempColor = new Color();
19
23
  }
20
24
 
21
25
  draw(renderer, skeleton) {
22
- // based on https://github.com/EsotericSoftware/spine-runtimes/blob/4.1/spine-ts/spine-canvas/src/SkeletonRenderer.ts
26
+ let clipper = this.clipper;
23
27
  let drawOrder = skeleton.drawOrder;
24
28
  let skeletonColor = skeleton.color;
25
-
26
- if (this.debugRendering === true) {
27
- renderer.setColor("green");
28
- }
29
+ let clippingMask = this.clippingMask;
30
+ let debugRendering = this.debugRendering;
29
31
 
30
32
  for (var i = 0, n = drawOrder.length; i < n; i++) {
33
+ let clippedVertexSize = clipper.isClipping() ? 2 : this.vertexSize;
31
34
  let slot = drawOrder[i];
32
35
  let bone = slot.bone;
36
+ let image;
37
+ let region;
33
38
 
34
- if (!bone.active) continue;
39
+ if (!bone.active) {
40
+ clipper.clipEndWithSlot(slot);
41
+ renderer.clearMask();
42
+ continue;
43
+ }
35
44
 
36
45
  let attachment = slot.getAttachment();
37
46
 
38
47
  if (attachment instanceof RegionAttachment) {
39
- let region = attachment.region;
40
- let image = region.texture.getImage();
48
+ attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
49
+ region = attachment.region;
50
+ image = region.texture.getImage();
51
+ } else if (attachment instanceof MeshAttachment) {
52
+ /*
53
+ // commenting for now as totally untested
54
+ let mesh = attachment;
55
+ mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, worldVertices, 0, 2);
56
+ region = mesh.region;
57
+ image = mesh.region.texture.getImage();
58
+ */
59
+ console.warn("spine-plugin: MeshAttachment is not supported yet");
60
+ } else if (attachment instanceof ClippingAttachment) {
61
+ let clip = attachment;
62
+ let vertices = this.clippingVertices;
63
+ clipper.clipStart(slot, clip);
64
+ clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
65
+ clippingMask.setVertices(vertices, clip.worldVerticesLength);
66
+ if (debugRendering === true) {
67
+ renderer.setColor(clipDebugColor);
68
+ renderer.stroke(clippingMask);
69
+ }
70
+ continue;
71
+ } else {
72
+ clipper.clipEndWithSlot(slot);
73
+ renderer.clearMask();
74
+ continue;
75
+ }
76
+
77
+ if (typeof image !== "undefined") {
41
78
  let slotColor = slot.color;
42
79
  let regionColor = attachment.color;
43
80
  let blendMode = slot.data.blendMode;
@@ -48,8 +85,6 @@ export default class SkeletonRenderer {
48
85
  skeletonColor.b * slotColor.b * regionColor.b,
49
86
  skeletonColor.a * slotColor.a * regionColor.a);
50
87
 
51
- attachment.computeWorldVertices(slot, worldVertices, 0, 2);
52
-
53
88
  renderer.save();
54
89
  renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
55
90
  renderer.translate(attachment.offset[0], attachment.offset[1]);
@@ -72,12 +107,23 @@ export default class SkeletonRenderer {
72
107
  renderer.setTint(color);
73
108
  renderer.setBlendMode(blendModeLUT[blendMode]);
74
109
  renderer.setGlobalAlpha(color.a);
110
+
111
+ if (clipper.isClipping()) {
112
+ renderer.setMask(clippingMask);
113
+ }
114
+
75
115
  renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
76
- if (this.debugRendering === true) {
116
+
117
+ if (debugRendering === true) {
118
+ renderer.setColor(regionDebugColor);
77
119
  renderer.strokeRect(0, 0, w, h);
78
120
  }
121
+
79
122
  renderer.restore();
80
123
  }
124
+ clipper.clipEndWithSlot(slot);
125
+ renderer.clearMask();
81
126
  }
127
+ clipper.clipEnd();
82
128
  }
83
129
  }