@melonjs/spine-plugin 1.4.0 → 2.0.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,68 +0,0 @@
1
- import { event, video } from "melonjs";
2
- import * as spineWebGL from "@esotericsoftware/spine-webgl";
3
- import * as spineCanvas from "@esotericsoftware/spine-canvas";
4
-
5
- /**
6
- * @classdesc
7
- * An Asset Manager class to load spine assets
8
- */
9
- export default class AssetManager {
10
- asset_manager;
11
- pathPrefix;
12
-
13
- /**
14
- * @param {string} [pathPrefix=""] - a default path prefix for assets location
15
- */
16
- constructor(pathPrefix = "") {
17
- event.once(event.VIDEO_INIT, () => {
18
- this.pathPrefix = pathPrefix;
19
- if (video.renderer.WebGLVersion >= 1) {
20
- this.asset_manager = new spineWebGL.AssetManager(video.renderer.getContext(), this.pathPrefix);
21
- } else {
22
- // canvas renderer
23
- this.asset_manager = new spineCanvas.AssetManager(this.pathPrefix);
24
- }
25
- });
26
- }
27
-
28
- /**
29
- * set a default path prefix for assets location
30
- * @see loadAsset
31
- * @param {string} pathPrefix
32
- */
33
- setPrefix(pathPrefix) {
34
- this.asset_manager.pathPrefix = this.pathPrefix = pathPrefix;
35
- }
36
-
37
- /**
38
- * define all spine assets to be loaded
39
- * @see setPrefix
40
- * @see loadAll
41
- * @param {string} atlas
42
- * @param {string} skel
43
- * @example
44
- * // load spine assets
45
- * Spine.assetManager.setPrefix("data/spine/");
46
- * Spine.assetManager.loadAsset("alien.atlas", "alien-ess.json");
47
- * await Spine.assetManager.loadAll();
48
- */
49
- loadAsset(atlas, skel) {
50
- if (atlas) {
51
- this.asset_manager.loadTextureAtlas(atlas);
52
- }
53
-
54
- if (skel.endsWith(".skel")) {
55
- this.asset_manager.loadBinary(skel);
56
- } else {
57
- this.asset_manager.loadText(skel);
58
- }
59
- }
60
-
61
- /**
62
- * load all defined spine assets
63
- * @see loadAsset
64
- */
65
- loadAll() {
66
- return this.asset_manager.loadAll();
67
- }
68
- }
@@ -1,220 +0,0 @@
1
- import { Color as MColor, Math as MMath, Polygon } from "melonjs";
2
- import { SkeletonClipping, ClippingAttachment, MeshAttachment, RegionAttachment } from "@esotericsoftware/spine-core";
3
-
4
- const vertexSize = 2 + 2 + 4;
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);
11
-
12
- export default class SkeletonRenderer {
13
- skeletonRenderer;
14
- runtime;
15
- tintColor = new MColor();
16
- tempColor = new MColor();
17
- debugRendering = false;
18
- clipper = new SkeletonClipping();
19
- clippingVertices = [];
20
- clippingMask = new Polygon(0, 0);
21
-
22
- constructor(runtime) {
23
- this.runtime = runtime;
24
- this.skeletonRenderer = new runtime.SkeletonRenderer();
25
- }
26
-
27
- draw(renderer, skeleton) {
28
- let clipper = this.clipper;
29
- let drawOrder = skeleton.drawOrder;
30
- let skeletonColor = skeleton.color;
31
- let clippingMask = this.clippingMask;
32
- let debugRendering = this.debugRendering;
33
-
34
- for (var i = 0, n = drawOrder.length; i < n; i++) {
35
- let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
36
- let slot = drawOrder[i];
37
- let bone = slot.bone;
38
- let image;
39
- let region;
40
- let triangles;
41
-
42
- if (!bone.active) {
43
- clipper.clipEndWithSlot(slot);
44
- renderer.clearMask();
45
- continue;
46
- }
47
-
48
- let attachment = slot.getAttachment();
49
-
50
- if (attachment instanceof RegionAttachment) {
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") {
77
- let slotColor = slot.color;
78
- let regionColor = attachment.color;
79
- let blendMode = slot.data.blendMode;
80
- let color = this.tintColor;
81
-
82
- renderer.save();
83
-
84
- color.setFloat(skeletonColor.r * slotColor.r * regionColor.r,
85
- skeletonColor.g * slotColor.g * regionColor.g,
86
- skeletonColor.b * slotColor.b * regionColor.b,
87
- skeletonColor.a * slotColor.a * regionColor.a);
88
-
89
- renderer.setGlobalAlpha(color.a);
90
- renderer.setTint(color);
91
- renderer.setBlendMode(blendModeLUT[blendMode]);
92
-
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
- }
131
- }
132
-
133
- renderer.restore();
134
- }
135
- clipper.clipEndWithSlot(slot);
136
- renderer.clearMask();
137
- }
138
- clipper.clipEnd();
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
- }
220
- }
package/src/index.js DELETED
@@ -1,411 +0,0 @@
1
- import { Math, Renderable, Vector2d, video, loader, utils, event } from "melonjs";
2
- import * as spineWebGL from "@esotericsoftware/spine-webgl";
3
- import * as spineCanvas from "@esotericsoftware/spine-canvas";
4
- import { Vector2 } from "@esotericsoftware/spine-core";
5
-
6
- import AssetManager from "./AssetManager.js";
7
- import SkeletonRenderer from "./SkeletonRenderer.js";
8
-
9
- import { name, version, dependencies, homepage } from "../package.json";
10
-
11
- export let assetManager = new AssetManager();
12
-
13
- // a custom Spine parser for melonJS preloader
14
- function spineParser(data, onload, onerror) {
15
-
16
- // decompose data.src for the spine loader
17
- const ext = utils.file.getExtension(data.src);
18
- const basename = utils.file.getBasename(data.src);
19
- const path = utils.file.getPath(data.src);
20
- const filename = basename + "." + ext;
21
-
22
- // set url prefix
23
- assetManager.setPrefix(path);
24
-
25
- // load asset
26
- switch (ext) {
27
- case "atlas":
28
- assetManager.asset_manager.loadTextureAtlas(filename, onload, onerror);
29
- break;
30
- case "json":
31
- assetManager.asset_manager.loadText(filename, onload, onerror);
32
- break;
33
- case "skel":
34
- assetManager.asset_manager.loadBinary(filename, onload, onerror);
35
- break;
36
- default:
37
- throw "Spine plugin: unknown extension when preloading spine assets";
38
- }
39
-
40
- return 1;
41
- }
42
-
43
- // set the spine custom parser
44
- loader.setParser("spine", spineParser);
45
-
46
- // hello world
47
- event.once(event.VIDEO_INIT, () => {
48
- console.log(`${name} ${version} - spine runtime ${dependencies["@esotericsoftware/spine-core"]} | ${homepage}`);
49
- });
50
-
51
- /**
52
- * @classdesc
53
- * An object to display a Spine animated skeleton on screen.
54
- * @augments Renderable
55
- */
56
- export default class Spine extends Renderable {
57
- runtime;
58
- skeleton;
59
- animationState;
60
- skeletonRenderer;
61
- assetManager;
62
- root;
63
- boneOffset;
64
- boneSize;
65
-
66
- /**
67
- * @param {number} x - the x coordinates of the Spine object
68
- * @param {number} y - the y coordinates of the Spine object
69
- * @param {object} settings - Configuration parameters for the Spine object
70
- * @param {number} [settings.atlasFile] - the name of the atlasFile to be used to create this spine animation
71
- * @param {number} [settings.jsonFile] - the name of the atlasFile to be used to create this spine animation
72
- * @param {number} [settings.mixTime = 0.2] - the default mix duration to use when no mix duration has been defined between two animations.
73
- * @example
74
- * import * as Spine from '@melonjs/spine-plugin';
75
- * import * as me from 'melonjs';
76
- *
77
- * // prepare/declare assets for the preloader
78
- * const DataManifest = [
79
- * {
80
- * "name": "alien-ess.json",
81
- * "type": "spine",
82
- * "src": "data/spine/alien-ess.json"
83
- * },
84
- * {
85
- * "name": "alien.atlas",
86
- * "type": "spine",
87
- * "src": "data/spine/alien.atlas"
88
- * },
89
- * ]
90
- *
91
- * // create a new Spine Renderable
92
- * let spineAlien = new Spine(100, 100, {atlasFile: "alien.atlas", jsonFile: "alien-ess.json"});
93
- *
94
- * // set default animation
95
- * spineAlien.setAnimation(0, "death", true);
96
- *
97
- * // add it to the game world
98
- * me.game.world.addChild(spineAlien);
99
- */
100
- constructor(x, y, settings) {
101
- super(x, y, settings.width, settings.height);
102
-
103
- if (video.renderer.WebGLVersion >= 1) {
104
- this.runtime = spineWebGL;
105
- } else {
106
- this.runtime = spineCanvas;
107
- }
108
-
109
- this.assetManager = assetManager.asset_manager;
110
- this.skeletonRenderer = new SkeletonRenderer(this.runtime);
111
-
112
- // force anchorPoint to 0,0
113
- this.anchorPoint.set(0, 0);
114
-
115
- // displaying order
116
- if (typeof settings.z !== "undefined") {
117
- this.pos.z = settings.z;
118
- }
119
-
120
- // use internally when calulcating bounds
121
- this.boneOffset = new Vector2();
122
- this.boneSize = new Vector2();
123
-
124
- // default mixTime
125
- this.mixTime = typeof settings.mixTime !== "undefined" ? settings.mixTime : 0.2;
126
-
127
-
128
- if (settings.jsonFile) {
129
- this.jsonFile = settings.jsonFile;
130
- this.atlasFile = settings.atlasFile;
131
- this.setSkeleton(this.atlasFile, this.jsonFile);
132
- }
133
- }
134
-
135
- /**
136
- * Whether to enabler the debug mode when rendering the spine object
137
- * @default false
138
- * @type {boolean}
139
- */
140
- get debugRendering() {
141
- return this.skeletonRenderer.debugRendering;
142
- }
143
-
144
- set debugRendering(value) {
145
- this.skeletonRenderer.debugRendering = value;
146
- }
147
-
148
- /**
149
- * set and load the given skeleton atlas and json definition files
150
- * (use this if you did not specify any json or atlas through the constructor)
151
- * @param {number} [atlasFile] - the name of the atlasFile to be used to create this spine animation
152
- * @param {number} [jsonFile] - the name of the atlasFile to be used to create this spine animation
153
- * @example
154
- * // create a new Spine Renderable
155
- * let spineAlien = new Spine(100, 100);
156
- *
157
- * // set the skeleton
158
- * spineAlien.setSkeleton("alien.atlas", "alien-ess.json");
159
- *
160
- * // set default animation
161
- * spineAlien.setAnimation(0, "death", true);
162
- *
163
- * // add it to the game world
164
- * me.game.world.addChild(spineAlien);
165
- */
166
- setSkeleton(atlasFile, jsonFile) {
167
- // Create the texture atlas and skeleton data.
168
- let atlas = this.assetManager.require(atlasFile);
169
- let atlasLoader = new this.runtime.AtlasAttachmentLoader(atlas);
170
- let skeletonJson = new this.runtime.SkeletonJson(atlasLoader);
171
- let skeletonData = skeletonJson.readSkeletonData(this.assetManager.require(jsonFile));
172
-
173
- // Instantiate a new skeleton based on the atlas and skeleton data.
174
- this.skeleton = new this.runtime.Skeleton(skeletonData);
175
- this.skeleton.setToSetupPose();
176
- this.skeleton.updateWorldTransform();
177
-
178
- // Setup an animation state with a default mix of 0.2 seconds.
179
- var animationStateData = new this.runtime.AnimationStateData(this.skeleton.data);
180
- animationStateData.defaultMix = this.mixTime;
181
- this.animationState = new this.runtime.AnimationState(animationStateData);
182
-
183
- // get a reference to the root bone
184
- this.root = this.skeleton.getRootBone();
185
- // Spine uses Y-up, melonJS uses Y-down
186
- this.root.scaleY *= -1;
187
-
188
- // mark the object as dirty
189
- this.isDirty = true;
190
- }
191
-
192
- /**
193
- * Rotate this Spine object by the specified angle (in radians).
194
- * @param {number} angle - The angle to rotate (in radians)
195
- * @param {Vector2d|ObservableVector2d} [v] - an optional point to rotate around
196
- * @returns {Spine} Reference to this object for method chaining
197
- */
198
- rotate(angle, v) {
199
- // rotation for rootBone is in degrees (anti-clockwise)
200
- this.skeleton.getRootBone().rotation -= Math.radToDeg(angle) + 90;
201
- // melonJS rotate method takes radians
202
- return super.rotate(angle, v);
203
- }
204
-
205
- /**
206
- * scale the Spine object around his anchor point. Scaling actually applies changes
207
- * to the currentTransform member wich is used by the renderer to scale the object
208
- * when rendering. It does not scale the object itself. For example if the renderable
209
- * is an image, the image.width and image.height properties are unaltered but the currentTransform
210
- * member will be changed.
211
- * @param {number} x - a number representing the abscissa of the scaling vector.
212
- * @param {number} [y=x] - a number representing the ordinate of the scaling vector.
213
- * @returns {Spine} Reference to this object for method chaining
214
- */
215
- scale(x, y = x) {
216
- // untested
217
- return super.scale(x, y);
218
- }
219
-
220
- /**
221
- * update the bounding box for this spine object.
222
- * (this will automatically update the bounds of the entire skeleton animation)
223
- * @param {boolean} [absolute=true] - update the bounds size and position in (world) absolute coordinates
224
- * @returns {Bounds} this shape bounding box Rectangle object
225
- */
226
- updateBounds(absolute = true) {
227
- if (this.isRenderable) {
228
- let bounds = this.getBounds();
229
- let isIdentity = this.autoTransform === true && this.currentTransform.isIdentity();
230
-
231
- bounds.clear();
232
-
233
- if (typeof this.skeleton !== "undefined") {
234
- let rootBone = this.skeleton.getRootBone();
235
- let boneOffset = this.boneOffset;
236
- let boneSize = this.boneSize;
237
-
238
- this.skeleton.getBounds(boneOffset, boneSize);
239
-
240
- bounds.addFrame(
241
- boneOffset.x - rootBone.x,
242
- boneOffset.y - rootBone.y,
243
- boneSize.x + boneOffset.x - rootBone.x,
244
- boneSize.y + boneOffset.y - rootBone.y,
245
- !isIdentity ? this.currentTransform : undefined
246
- );
247
- } else {
248
- bounds.addFrame(
249
- 0,
250
- 0,
251
- this.width,
252
- this.height,
253
- !isIdentity ? this.currentTransform : undefined
254
- );
255
- }
256
-
257
- if (absolute === true) {
258
- var absPos = this.getAbsolutePosition();
259
- bounds.centerOn(absPos.x + bounds.centerX, absPos.y + bounds.centerY);
260
- }
261
- return bounds;
262
-
263
- } else {
264
- // manage the case where updateBounds is called
265
- // before the object being yet properly initialized
266
- return super.updateBounds(absolute);
267
- }
268
- }
269
-
270
- /**
271
- * update function (automatically called by melonJS).
272
- * @param {number} dt - time since the last update in milliseconds.
273
- * @returns {boolean} true if the renderable is dirty
274
- */
275
- update(dt) {
276
- if (typeof this.skeleton !== "undefined") {
277
- let rootBone = this.skeleton.getRootBone();
278
-
279
- // update the root bone position
280
- if (rootBone.x !== this.pos.x) {
281
- rootBone.x = this.pos.x;
282
- }
283
- if (rootBone.y !== this.pos.y) {
284
- rootBone.y = this.pos.y;
285
- }
286
-
287
- // Update and apply the animation state, update the skeleton's
288
- // world transforms and render the skeleton.
289
- this.animationState.update(dt / 1000);
290
- this.animationState.apply(this.skeleton);
291
- this.skeleton.updateWorldTransform();
292
-
293
- this.updateBounds();
294
- }
295
- return true;
296
- }
297
-
298
-
299
- /**
300
- * draw this spine object
301
- * @param {CanvasRenderer|WebGLRenderer} renderer - a renderer instance
302
- * @param {Camera2d} [viewport] - the viewport to (re)draw
303
- */
304
- draw(renderer) {
305
- this.skeletonRenderer.draw(renderer, this.skeleton);
306
- }
307
-
308
- /**
309
- * Sets the current animation for a track, discarding any queued animations.
310
- * @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.
311
- * @param {number} [index] - the animation index
312
- * @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.
313
- * @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.
314
- */
315
- setAnimationByIndex(track_index, index, loop = false) {
316
- if (index < 0 || index >= this.skeleton.data.animations.length) {
317
- return (console.log("Animation Index not found"));
318
- } else {
319
- this.animationState.setAnimation(track_index, this.skeleton.data.animations[index].name, loop);
320
- }
321
- }
322
-
323
- /**
324
- * Sets the current animation for a track, discarding any queued animations.
325
- * @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.
326
- * @param {string} [name] - the animation name
327
- * @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.
328
- * @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.
329
- * @example
330
- * // set the current animation
331
- * spineAlien.setAnimation(0, "death", true);
332
- */
333
- setAnimation(track_index, name, loop = false) {
334
- this.animationState.setAnimation(track_index, name, loop);
335
- }
336
-
337
- /**
338
- * Adds an animation to be played after the current or last queued animation for a track, and sets the track entry's mixDuration.
339
- * @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.
340
- * @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.
341
- */
342
- addAnimationByIndex(track_index, index, loop = false, delay = 0) {
343
- if (index < 0 || index >= this.skeleton.data.animations.length) {
344
- return (console.log("Animation Index not found"));
345
- } else {
346
- this.animationState.addAnimation(track_index, this.skeleton.data.animations[index].name, loop, delay);
347
- }
348
- }
349
-
350
- addAnimationByName(track_index, animationName, loop = false, delay = 0) {
351
- this.animationState.addAnimation(track_index, animationName, loop, delay);
352
- }
353
-
354
- getSpinePosition() {
355
- return new Vector2d(this.pos.x, this.pos.y);
356
- }
357
-
358
- setSpineSize(width, height) {
359
- this.width = width;
360
- this.height = height;
361
- }
362
-
363
- getSpineSize() {
364
- return {
365
- width: this.width,
366
- height: this.height
367
- };
368
- }
369
-
370
- /**
371
- * Set the default mix duration to use when no mix duration has been defined between two animations.
372
- * @param {number} mixTime
373
- */
374
- setDefaultMixTime(mixTime) {
375
- this.animationState.data.defaultMix = this.mixTime = mixTime;
376
- }
377
-
378
- /**
379
- * Sets a mix duration by animation name.
380
- */
381
- setTransitionMixTime(firstAnimation, secondAnimation, mixTime) {
382
- this.animationState.setMix(firstAnimation, secondAnimation, mixTime);
383
- }
384
-
385
- /**
386
- * Sets a skin by name.
387
- * @param {string} skinName
388
- * @example
389
- * // create a new Spine Renderable
390
- * let spineAlien = new Spine(100, 100, {atlasFile: "mix-and-match-pma.atlas", jsonFile: "mix-and-match-pro.json"});
391
- *
392
- * // set default animation
393
- * spineAlien.setAnimation(0, "dance", true);
394
- *
395
- * // set default skin
396
- * spineAlien.setSkinByName("full-skins/girl");
397
- *
398
- * // add it to the game world
399
- * me.game.world.addChild(spineAlien);
400
- */
401
- setSkinByName(skinName) {
402
- this.skeleton.setSkinByName(skinName);
403
- }
404
-
405
- /**
406
- * Sets this slot to the setup pose.
407
- */
408
- setToSetupPose() {
409
- this.skeleton.setToSetupPose();
410
- }
411
- }