@melonjs/spine-plugin 1.2.0 → 1.3.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 1.3.0 - 2023-08-28å
4
+
5
+ - add support for Mesh Attachement
6
+ - added more examples under the test folder and separated them into individual files
7
+ - add a fullscreen option to examples (pressing the "F" key toggles fullscreen mode)
8
+
9
+ ## 1.2.1 - 2023-08-23
10
+
11
+ - code refactoring and optimization to prepare for future feature additions
12
+ - fix URLs in the package.json file
13
+
14
+ ## 1.2.0 - 2023-08-22
15
+
16
+ - add support for clipping (coin example is now rendered properly)
17
+
18
+ ## 1.1.0 - 2023-08-19
19
+
20
+ - add some basic debug rendering
21
+ - optimize code (remove unneeded logic)
22
+
23
+ ## 1.0.0 - 2023-08-16
24
+
25
+ initial release
package/README.md CHANGED
@@ -1,6 +1,6 @@
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
5
  ![melonjs-spine-gif](https://github.com/melonjs/spine-plugin/assets/4033090/dc259c8e-def6-419e-83a9-cda374715686)
6
6
 
@@ -14,7 +14,7 @@ a [Spine](http://en.esotericsoftware.com/spine-in-depth) 4.1 plugin implementati
14
14
  Installation
15
15
  -------------------------------------------------------------------------------
16
16
  this plugin is already bundled with the required Spine runtime, so there is no need to install it separately.
17
- >Note: this plugin requires melonJS version 15.9 or higher.
17
+ >Note: this plugin requires melonJS version 15.9.2 or higher.
18
18
 
19
19
  To install the plugin using npm :
20
20
 
@@ -4070,17 +4070,17 @@ 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;
4078
- vertexSize: number;
4076
+ tempColor: Color$1;
4079
4077
  debugRendering: boolean;
4080
4078
  clipper: SkeletonClipping;
4081
4079
  clippingVertices: any[];
4082
4080
  clippingMask: Polygon;
4083
4081
  draw(renderer: any, skeleton: any): void;
4082
+ drawTriangle(renderer: any, img: any, x0: any, y0: any, u0: any, v0: any, x1: any, y1: any, u1: any, v1: any, x2: any, y2: any, u2: any, v2: any): void;
4083
+ computeMeshVertices(slot: any, mesh: any, pma: boolean | undefined, vertexSize: any): void;
4084
4084
  }
4085
4085
  import { Vector2d } from 'melonjs';
4086
4086
  /******************************************************************************
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * melonJS Spine plugin - v1.2.0
2
+ * melonJS Spine plugin - v1.3.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
@@ -14929,16 +14929,19 @@ class AssetManager {
14929
14929
  }
14930
14930
  }
14931
14931
 
14932
- const worldVertices = new Float32Array(8);
14932
+ const vertexSize = 2 + 2 + 4;
14933
14933
  const blendModeLUT = ["normal", "additive", "multiply", "screen"];
14934
+ const regionDebugColor = "green";
14935
+ const meshDebugColor = "yellow";
14936
+ const clipDebugColor = "blue";
14937
+
14938
+ let worldVertices = new Float32Array(vertexSize * 1024);
14934
14939
 
14935
14940
  class SkeletonRenderer {
14936
- isWebGLRenderer;
14937
14941
  skeletonRenderer;
14938
14942
  runtime;
14939
- tempColor = new Color();
14940
14943
  tintColor = new Color$1();
14941
- vertexSize = 2 + 2 + 4;
14944
+ tempColor = new Color$1();
14942
14945
  debugRendering = false;
14943
14946
  clipper = new SkeletonClipping();
14944
14947
  clippingVertices = [];
@@ -14947,18 +14950,22 @@ class SkeletonRenderer {
14947
14950
  constructor(runtime) {
14948
14951
  this.runtime = runtime;
14949
14952
  this.skeletonRenderer = new runtime.SkeletonRenderer();
14950
- this.tempColor = new Color();
14951
14953
  }
14952
14954
 
14953
14955
  draw(renderer, skeleton) {
14954
14956
  let clipper = this.clipper;
14955
14957
  let drawOrder = skeleton.drawOrder;
14956
14958
  let skeletonColor = skeleton.color;
14959
+ let clippingMask = this.clippingMask;
14960
+ let debugRendering = this.debugRendering;
14957
14961
 
14958
14962
  for (var i = 0, n = drawOrder.length; i < n; i++) {
14959
- let clippedVertexSize = clipper.isClipping() ? 2 : this.vertexSize;
14963
+ let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
14960
14964
  let slot = drawOrder[i];
14961
14965
  let bone = slot.bone;
14966
+ let image;
14967
+ let region;
14968
+ let triangles;
14962
14969
 
14963
14970
  if (!bone.active) {
14964
14971
  clipper.clipEndWithSlot(slot);
@@ -14969,78 +14976,175 @@ class SkeletonRenderer {
14969
14976
  let attachment = slot.getAttachment();
14970
14977
 
14971
14978
  if (attachment instanceof RegionAttachment) {
14972
- let region = attachment.region;
14973
- let image = region.texture.getImage();
14979
+ attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
14980
+ region = attachment.region;
14981
+ image = region.texture.getImage();
14982
+ } else if (attachment instanceof MeshAttachment) {
14983
+ this.computeMeshVertices(slot, attachment, false, clippedVertexSize);
14984
+ triangles = attachment.triangles;
14985
+ region = attachment.region;
14986
+ image = region.texture.getImage();
14987
+ } else if (attachment instanceof ClippingAttachment) {
14988
+ let clip = attachment;
14989
+ let vertices = this.clippingVertices;
14990
+ clipper.clipStart(slot, clip);
14991
+ clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
14992
+ clippingMask.setVertices(vertices, clip.worldVerticesLength);
14993
+ if (debugRendering === true) {
14994
+ renderer.setColor(clipDebugColor);
14995
+ renderer.stroke(clippingMask);
14996
+ }
14997
+ continue;
14998
+ } else {
14999
+ clipper.clipEndWithSlot(slot);
15000
+ renderer.clearMask();
15001
+ continue;
15002
+ }
15003
+
15004
+ if (typeof image !== "undefined") {
14974
15005
  let slotColor = slot.color;
14975
15006
  let regionColor = attachment.color;
14976
15007
  let blendMode = slot.data.blendMode;
14977
15008
  let color = this.tintColor;
14978
15009
 
15010
+ renderer.save();
15011
+
14979
15012
  color.setFloat(skeletonColor.r * slotColor.r * regionColor.r,
14980
15013
  skeletonColor.g * slotColor.g * regionColor.g,
14981
15014
  skeletonColor.b * slotColor.b * regionColor.b,
14982
15015
  skeletonColor.a * slotColor.a * regionColor.a);
14983
15016
 
14984
- attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
14985
-
14986
- renderer.save();
14987
- renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
14988
- renderer.translate(attachment.offset[0], attachment.offset[1]);
14989
- renderer.rotate(Math$1.degToRad(attachment.rotation));
14990
-
14991
- let atlasScale = attachment.width / region.originalWidth;
14992
- renderer.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);
14993
-
14994
- let w = region.width, h = region.height;
14995
- let hW = w / 2, hH = h / 2;
14996
- renderer.translate(hW, hH);
14997
- if (region.degrees === 90) {
14998
- let t = w;
14999
- w = h;
15000
- h = t;
15001
- renderer.rotate(-Math$1.ETA);
15002
- }
15003
- renderer.scale(1, -1);
15004
- renderer.translate(-hW, -hH);
15017
+ renderer.setGlobalAlpha(color.a);
15005
15018
  renderer.setTint(color);
15006
15019
  renderer.setBlendMode(blendModeLUT[blendMode]);
15007
- renderer.setGlobalAlpha(color.a);
15008
15020
 
15009
- if (clipper.isClipping()) {
15010
- renderer.setMask(this.clippingMask);
15011
- }
15021
+ if (typeof triangles !== "undefined") {
15022
+ let vertices = worldVertices;
15023
+ for (var j = 0; j < triangles.length; j += 3) {
15024
+ let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8;
15025
+ let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];
15026
+ let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];
15027
+ let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];
15012
15028
 
15013
- renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
15029
+ this.drawTriangle(renderer, image, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
15030
+ }
15031
+ } else {
15032
+ let atlasScale = attachment.width / region.originalWidth;
15033
+ let w = region.width, h = region.height;
15034
+ let hW = w / 2, hH = h / 2;
15014
15035
 
15015
- if (this.debugRendering === true) {
15016
- renderer.setColor("green");
15017
- renderer.strokeRect(0, 0, w, h);
15036
+ renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
15037
+ renderer.translate(attachment.offset[0], attachment.offset[1]);
15038
+ renderer.rotate(Math$1.degToRad(attachment.rotation));
15039
+ renderer.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);
15040
+ renderer.translate(hW, hH);
15041
+ if (region.degrees === 90) {
15042
+ let t = w;
15043
+ w = h;
15044
+ h = t;
15045
+ renderer.rotate(-Math$1.ETA);
15046
+ }
15047
+ renderer.scale(1, -1);
15048
+ renderer.translate(-hW, -hH);
15049
+
15050
+ if (clipper.isClipping()) {
15051
+ renderer.setMask(clippingMask);
15052
+ }
15053
+ renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
15054
+
15055
+ if (debugRendering === true) {
15056
+ renderer.setColor(regionDebugColor);
15057
+ renderer.strokeRect(0, 0, w, h);
15058
+ }
15018
15059
  }
15019
15060
 
15020
15061
  renderer.restore();
15021
- } else if (attachment instanceof MeshAttachment) {
15022
- // do nothing for now;
15023
- } else if (attachment instanceof ClippingAttachment) {
15024
- let clip = attachment;
15025
- let vertices = this.clippingVertices;
15026
- clipper.clipStart(slot, clip);
15027
- clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
15028
- this.clippingMask.setVertices(vertices, clip.worldVerticesLength);
15029
- if (this.debugRendering === true) {
15030
- renderer.setColor("blue");
15031
- renderer.stroke(this.clippingMask);
15032
- }
15033
- continue;
15034
- } else {
15035
- clipper.clipEndWithSlot(slot);
15036
- renderer.clearMask();
15037
- continue;
15038
15062
  }
15039
15063
  clipper.clipEndWithSlot(slot);
15040
15064
  renderer.clearMask();
15041
15065
  }
15042
15066
  clipper.clipEnd();
15043
15067
  }
15068
+
15069
+ drawTriangle(renderer, img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
15070
+ u0 *= img.width;
15071
+ v0 *= img.height;
15072
+ u1 *= img.width;
15073
+ v1 *= img.height;
15074
+ u2 *= img.width;
15075
+ v2 *= img.height;
15076
+
15077
+ renderer.save();
15078
+ renderer.beginPath();
15079
+ renderer.moveTo(x0, y0);
15080
+ renderer.lineTo(x1, y1);
15081
+ renderer.lineTo(x2, y2);
15082
+ renderer.closePath();
15083
+ renderer.setMask();
15084
+
15085
+ x1 -= x0;
15086
+ y1 -= y0;
15087
+ x2 -= x0;
15088
+ y2 -= y0;
15089
+
15090
+ u1 -= u0;
15091
+ v1 -= v0;
15092
+ u2 -= u0;
15093
+ v2 -= v0;
15094
+
15095
+ var det = 1 / (u1 * v2 - u2 * v1),
15096
+
15097
+ // linear transformation
15098
+ a = (v2 * x1 - v1 * x2) * det,
15099
+ b = (v2 * y1 - v1 * y2) * det,
15100
+ c = (u1 * x2 - u2 * x1) * det,
15101
+ d = (u1 * y2 - u2 * y1) * det,
15102
+
15103
+ // translation
15104
+ e = x0 - a * u0 - c * v0,
15105
+ f = y0 - b * u0 - d * v0;
15106
+
15107
+ renderer.transform(a, b, c, d, e, f);
15108
+ renderer.drawImage(img, 0, 0);
15109
+ renderer.clearMask();
15110
+ renderer.restore();
15111
+
15112
+ if (this.debugRendering === true) {
15113
+ renderer.setColor(meshDebugColor);
15114
+ renderer.stroke();
15115
+ }
15116
+
15117
+ }
15118
+
15119
+ computeMeshVertices(slot, mesh, pma = false, vertexSize) {
15120
+ let skeletonColor = slot.bone.skeleton.color;
15121
+ let slotColor = slot.color;
15122
+ let regionColor = mesh.color;
15123
+ let alpha = skeletonColor.a * slotColor.a * regionColor.a;
15124
+ let multiplier = pma ? alpha : 1;
15125
+
15126
+ this.tempColor.setFloat(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
15127
+ skeletonColor.g * slotColor.g * regionColor.g * multiplier,
15128
+ skeletonColor.b * slotColor.b * regionColor.b * multiplier,
15129
+ alpha);
15130
+
15131
+ if (worldVertices.length < mesh.worldVerticesLength) worldVertices = new Float32Array(mesh.worldVerticesLength);
15132
+ mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, worldVertices, 0, vertexSize);
15133
+
15134
+ let uvs = mesh.uvs;
15135
+ let color = this.tempColor.toArray();
15136
+ let vertices = worldVertices;
15137
+ let vertexCount = mesh.worldVerticesLength / 2;
15138
+ for (let i = 0, u = 0, v = 2; i < vertexCount; i++) {
15139
+ vertices[v++] = color[0];
15140
+ vertices[v++] = color[1];
15141
+ vertices[v++] = color[2];
15142
+ vertices[v++] = color[3];
15143
+ vertices[v++] = uvs[u++];
15144
+ vertices[v++] = uvs[u++];
15145
+ v += 2;
15146
+ }
15147
+ }
15044
15148
  }
15045
15149
 
15046
15150
  let assetManager = new AssetManager();
package/package.json CHANGED
@@ -1,27 +1,31 @@
1
1
  {
2
2
  "name": "@melonjs/spine-plugin",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
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,10 +42,11 @@
38
42
  "src/",
39
43
  "package.json",
40
44
  "README.md",
41
- "LICENSE"
45
+ "LICENSE",
46
+ "CHANGELOG.md"
42
47
  ],
43
48
  "peerDependencies": {
44
- "melonjs": "^15.9.0"
49
+ "melonjs": "^15.9.2"
45
50
  },
46
51
  "dependencies": {
47
52
  "@esotericsoftware/spine-canvas": "^4.2.18",
@@ -49,17 +54,17 @@
49
54
  "@esotericsoftware/spine-webgl": "^4.2.18"
50
55
  },
51
56
  "devDependencies": {
52
- "@babel/eslint-parser": "^7.22.0",
57
+ "@babel/eslint-parser": "^7.22.11",
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
- "del-cli": "^5.0.0",
58
- "eslint": "^8.47.0",
62
+ "del-cli": "^5.0.1",
63
+ "eslint": "^8.48.0",
59
64
  "eslint-plugin-jsdoc": "^46.5.0",
60
- "rollup": "^3.28.0",
65
+ "rollup": "^3.28.1",
61
66
  "rollup-plugin-bundle-size": "^1.0.3",
62
- "typescript": "^5.1.6"
67
+ "typescript": "^5.2.2"
63
68
  },
64
69
  "scripts": {
65
70
  "build": "npm run clean && npm run lint && rollup -c --silent && npm run types",
@@ -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,16 +1,19 @@
1
1
  import { Color as MColor, Math as MMath, Polygon } from "melonjs";
2
- import { SkeletonClipping, ClippingAttachment, MeshAttachment, RegionAttachment, Color } from "@esotericsoftware/spine-core";
2
+ import { SkeletonClipping, ClippingAttachment, MeshAttachment, RegionAttachment } from "@esotericsoftware/spine-core";
3
3
 
4
- const worldVertices = new Float32Array(8);
4
+ const vertexSize = 2 + 2 + 4;
5
5
  const blendModeLUT = ["normal", "additive", "multiply", "screen"];
6
+ const regionDebugColor = "green";
7
+ const meshDebugColor = "yellow";
8
+ const clipDebugColor = "blue";
9
+
10
+ let worldVertices = new Float32Array(vertexSize * 1024);
6
11
 
7
12
  export default class SkeletonRenderer {
8
- isWebGLRenderer;
9
13
  skeletonRenderer;
10
14
  runtime;
11
- tempColor = new Color();
12
15
  tintColor = new MColor();
13
- vertexSize = 2 + 2 + 4;
16
+ tempColor = new MColor();
14
17
  debugRendering = false;
15
18
  clipper = new SkeletonClipping();
16
19
  clippingVertices = [];
@@ -19,18 +22,22 @@ export default class SkeletonRenderer {
19
22
  constructor(runtime) {
20
23
  this.runtime = runtime;
21
24
  this.skeletonRenderer = new runtime.SkeletonRenderer();
22
- this.tempColor = new Color();
23
25
  }
24
26
 
25
27
  draw(renderer, skeleton) {
26
28
  let clipper = this.clipper;
27
29
  let drawOrder = skeleton.drawOrder;
28
30
  let skeletonColor = skeleton.color;
31
+ let clippingMask = this.clippingMask;
32
+ let debugRendering = this.debugRendering;
29
33
 
30
34
  for (var i = 0, n = drawOrder.length; i < n; i++) {
31
- let clippedVertexSize = clipper.isClipping() ? 2 : this.vertexSize;
35
+ let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
32
36
  let slot = drawOrder[i];
33
37
  let bone = slot.bone;
38
+ let image;
39
+ let region;
40
+ let triangles;
34
41
 
35
42
  if (!bone.active) {
36
43
  clipper.clipEndWithSlot(slot);
@@ -41,76 +48,173 @@ export default class SkeletonRenderer {
41
48
  let attachment = slot.getAttachment();
42
49
 
43
50
  if (attachment instanceof RegionAttachment) {
44
- let region = attachment.region;
45
- let image = region.texture.getImage();
51
+ attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
52
+ region = attachment.region;
53
+ image = region.texture.getImage();
54
+ } else if (attachment instanceof MeshAttachment) {
55
+ this.computeMeshVertices(slot, attachment, false, clippedVertexSize);
56
+ triangles = attachment.triangles;
57
+ region = attachment.region;
58
+ image = region.texture.getImage();
59
+ } else if (attachment instanceof ClippingAttachment) {
60
+ let clip = attachment;
61
+ let vertices = this.clippingVertices;
62
+ clipper.clipStart(slot, clip);
63
+ clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
64
+ clippingMask.setVertices(vertices, clip.worldVerticesLength);
65
+ if (debugRendering === true) {
66
+ renderer.setColor(clipDebugColor);
67
+ renderer.stroke(clippingMask);
68
+ }
69
+ continue;
70
+ } else {
71
+ clipper.clipEndWithSlot(slot);
72
+ renderer.clearMask();
73
+ continue;
74
+ }
75
+
76
+ if (typeof image !== "undefined") {
46
77
  let slotColor = slot.color;
47
78
  let regionColor = attachment.color;
48
79
  let blendMode = slot.data.blendMode;
49
80
  let color = this.tintColor;
50
81
 
82
+ renderer.save();
83
+
51
84
  color.setFloat(skeletonColor.r * slotColor.r * regionColor.r,
52
85
  skeletonColor.g * slotColor.g * regionColor.g,
53
86
  skeletonColor.b * slotColor.b * regionColor.b,
54
87
  skeletonColor.a * slotColor.a * regionColor.a);
55
88
 
56
- attachment.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
57
-
58
- renderer.save();
59
- renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
60
- renderer.translate(attachment.offset[0], attachment.offset[1]);
61
- renderer.rotate(MMath.degToRad(attachment.rotation));
62
-
63
- let atlasScale = attachment.width / region.originalWidth;
64
- renderer.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);
65
-
66
- let w = region.width, h = region.height;
67
- let hW = w / 2, hH = h / 2;
68
- renderer.translate(hW, hH);
69
- if (region.degrees === 90) {
70
- let t = w;
71
- w = h;
72
- h = t;
73
- renderer.rotate(-MMath.ETA);
74
- }
75
- renderer.scale(1, -1);
76
- renderer.translate(-hW, -hH);
89
+ renderer.setGlobalAlpha(color.a);
77
90
  renderer.setTint(color);
78
91
  renderer.setBlendMode(blendModeLUT[blendMode]);
79
- renderer.setGlobalAlpha(color.a);
80
-
81
- if (clipper.isClipping()) {
82
- renderer.setMask(this.clippingMask);
83
- }
84
92
 
85
- renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
86
-
87
- if (this.debugRendering === true) {
88
- renderer.setColor("green");
89
- renderer.strokeRect(0, 0, w, h);
93
+ if (typeof triangles !== "undefined") {
94
+ let vertices = worldVertices;
95
+ for (var j = 0; j < triangles.length; j += 3) {
96
+ let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8;
97
+ let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];
98
+ let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];
99
+ let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];
100
+
101
+ this.drawTriangle(renderer, image, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
102
+ }
103
+ } else {
104
+ let atlasScale = attachment.width / region.originalWidth;
105
+ let w = region.width, h = region.height;
106
+ let hW = w / 2, hH = h / 2;
107
+
108
+ renderer.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
109
+ renderer.translate(attachment.offset[0], attachment.offset[1]);
110
+ renderer.rotate(MMath.degToRad(attachment.rotation));
111
+ renderer.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);
112
+ renderer.translate(hW, hH);
113
+ if (region.degrees === 90) {
114
+ let t = w;
115
+ w = h;
116
+ h = t;
117
+ renderer.rotate(-MMath.ETA);
118
+ }
119
+ renderer.scale(1, -1);
120
+ renderer.translate(-hW, -hH);
121
+
122
+ if (clipper.isClipping()) {
123
+ renderer.setMask(clippingMask);
124
+ }
125
+ renderer.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
126
+
127
+ if (debugRendering === true) {
128
+ renderer.setColor(regionDebugColor);
129
+ renderer.strokeRect(0, 0, w, h);
130
+ }
90
131
  }
91
132
 
92
133
  renderer.restore();
93
- } else if (attachment instanceof MeshAttachment) {
94
- // do nothing for now;
95
- } else if (attachment instanceof ClippingAttachment) {
96
- let clip = attachment;
97
- let vertices = this.clippingVertices;
98
- clipper.clipStart(slot, clip);
99
- clip.computeWorldVertices(slot, 0, clip.worldVerticesLength, vertices, 0, 2);
100
- this.clippingMask.setVertices(vertices, clip.worldVerticesLength);
101
- if (this.debugRendering === true) {
102
- renderer.setColor("blue");
103
- renderer.stroke(this.clippingMask);
104
- }
105
- continue;
106
- } else {
107
- clipper.clipEndWithSlot(slot);
108
- renderer.clearMask();
109
- continue;
110
134
  }
111
135
  clipper.clipEndWithSlot(slot);
112
136
  renderer.clearMask();
113
137
  }
114
138
  clipper.clipEnd();
115
139
  }
140
+
141
+ drawTriangle(renderer, img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
142
+ u0 *= img.width;
143
+ v0 *= img.height;
144
+ u1 *= img.width;
145
+ v1 *= img.height;
146
+ u2 *= img.width;
147
+ v2 *= img.height;
148
+
149
+ renderer.save();
150
+ renderer.beginPath();
151
+ renderer.moveTo(x0, y0);
152
+ renderer.lineTo(x1, y1);
153
+ renderer.lineTo(x2, y2);
154
+ renderer.closePath();
155
+ renderer.setMask();
156
+
157
+ x1 -= x0;
158
+ y1 -= y0;
159
+ x2 -= x0;
160
+ y2 -= y0;
161
+
162
+ u1 -= u0;
163
+ v1 -= v0;
164
+ u2 -= u0;
165
+ v2 -= v0;
166
+
167
+ var det = 1 / (u1 * v2 - u2 * v1),
168
+
169
+ // linear transformation
170
+ a = (v2 * x1 - v1 * x2) * det,
171
+ b = (v2 * y1 - v1 * y2) * det,
172
+ c = (u1 * x2 - u2 * x1) * det,
173
+ d = (u1 * y2 - u2 * y1) * det,
174
+
175
+ // translation
176
+ e = x0 - a * u0 - c * v0,
177
+ f = y0 - b * u0 - d * v0;
178
+
179
+ renderer.transform(a, b, c, d, e, f);
180
+ renderer.drawImage(img, 0, 0);
181
+ renderer.clearMask();
182
+ renderer.restore();
183
+
184
+ if (this.debugRendering === true) {
185
+ renderer.setColor(meshDebugColor);
186
+ renderer.stroke();
187
+ }
188
+
189
+ }
190
+
191
+ computeMeshVertices(slot, mesh, pma = false, vertexSize) {
192
+ let skeletonColor = slot.bone.skeleton.color;
193
+ let slotColor = slot.color;
194
+ let regionColor = mesh.color;
195
+ let alpha = skeletonColor.a * slotColor.a * regionColor.a;
196
+ let multiplier = pma ? alpha : 1;
197
+
198
+ this.tempColor.setFloat(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
199
+ skeletonColor.g * slotColor.g * regionColor.g * multiplier,
200
+ skeletonColor.b * slotColor.b * regionColor.b * multiplier,
201
+ alpha);
202
+
203
+ if (worldVertices.length < mesh.worldVerticesLength) worldVertices = new Float32Array(mesh.worldVerticesLength);
204
+ mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, worldVertices, 0, vertexSize);
205
+
206
+ let uvs = mesh.uvs;
207
+ let color = this.tempColor.toArray();
208
+ let vertices = worldVertices;
209
+ let vertexCount = mesh.worldVerticesLength / 2;
210
+ for (let i = 0, u = 0, v = 2; i < vertexCount; i++) {
211
+ vertices[v++] = color[0];
212
+ vertices[v++] = color[1];
213
+ vertices[v++] = color[2];
214
+ vertices[v++] = color[3];
215
+ vertices[v++] = uvs[u++];
216
+ vertices[v++] = uvs[u++];
217
+ v += 2;
218
+ }
219
+ }
116
220
  }