diff --git a/spine-ts/biome.json b/spine-ts/biome.json index f274f07a7..3de998f02 100644 --- a/spine-ts/biome.json +++ b/spine-ts/biome.json @@ -6,9 +6,15 @@ "enabled": true, "rules": { "recommended": true, + "complexity": { + "noUselessConstructor": "off" + }, "correctness": { "noUnusedFunctionParameters": "off" }, + "style": { + "useExponentiationOperator": "off" + }, "suspicious": { "noAssignInExpressions": "off" } diff --git a/spine-ts/spine-core/src/Animation.ts b/spine-ts/spine-core/src/Animation.ts index ea9fd36d9..2fc2c98c0 100644 --- a/spine-ts/spine-core/src/Animation.ts +++ b/spine-ts/spine-core/src/Animation.ts @@ -27,20 +27,20 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { VertexAttachment, Attachment } from "./attachments/Attachment.js"; -import { HasTextureRegion } from "./attachments/HasTextureRegion.js"; +import { type Attachment, VertexAttachment } from "./attachments/Attachment.js"; +import type { HasTextureRegion } from "./attachments/HasTextureRegion.js"; import { SequenceMode, SequenceModeValues } from "./attachments/Sequence.js"; -import { Inherit } from "./BoneData.js"; -import { BoneLocal } from "./BoneLocal.js"; -import { Event } from "./Event.js"; +import type { Inherit } from "./BoneData.js"; +import type { BoneLocal } from "./BoneLocal.js"; +import type { Event } from "./Event.js"; import { PathConstraint } from "./PathConstraint.js"; -import { PhysicsConstraint } from "./PhysicsConstraint.js"; -import { PhysicsConstraintData } from "./PhysicsConstraintData.js"; -import { PhysicsConstraintPose } from "./PhysicsConstraintPose.js"; -import { Skeleton } from "./Skeleton.js"; -import { Slot } from "./Slot.js"; -import { SlotPose } from "./SlotPose.js"; -import { MathUtils, NumberArrayLike, StringSet, Utils } from "./Utils.js"; +import type { PhysicsConstraint } from "./PhysicsConstraint.js"; +import type { PhysicsConstraintData } from "./PhysicsConstraintData.js"; +import type { PhysicsConstraintPose } from "./PhysicsConstraintPose.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Slot } from "./Slot.js"; +import type { SlotPose } from "./SlotPose.js"; +import { MathUtils, type NumberArrayLike, StringSet, Utils } from "./Utils.js"; /** A simple container for a list of timelines and a name. */ export class Animation { @@ -62,7 +62,7 @@ export class Animation { this.name = name; this.duration = duration; this.timelineIds = new StringSet(); - this.bones = new Array(); + this.bones = [] as number[]; this.setTimelines(timelines); } @@ -114,12 +114,12 @@ export class Animation { blend: MixBlend, direction: MixDirection, appliedPose: boolean) { if (!skeleton) throw new Error("skeleton cannot be null."); - if (loop && this.duration != 0) { + if (loop && this.duration !== 0) { time %= this.duration; if (lastTime > 0) lastTime %= this.duration; } - let timelines = this.timelines; + const timelines = this.timelines; for (let i = 0, n = timelines.length; i < n; i++) timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction, appliedPose); } @@ -249,7 +249,7 @@ export abstract class Timeline { * @param time Must be >= the first value in frames. * @return The index of the first value <= time. */ static search (frames: NumberArrayLike, time: number, step = 1) { - let n = frames.length; + const n = frames.length; for (let i = step; i < n; i += step) if (frames[i] > time) return i - step; return n - step; @@ -262,7 +262,7 @@ export interface SlotTimeline { slotIndex: number; } -export function isSlotTimeline (obj: any): obj is SlotTimeline { +export function isSlotTimeline (obj: Timeline & Partial): obj is Timeline & SlotTimeline { return typeof obj === 'object' && obj !== null && typeof obj.slotIndex === 'number'; } @@ -289,9 +289,9 @@ export abstract class CurveTimeline extends Timeline { /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger * than the actual number of Bezier curves. */ shrink (bezierCount: number) { - let size = this.getFrameCount() + bezierCount * 18/*BEZIER_SIZE*/; + const size = this.getFrameCount() + bezierCount * 18/*BEZIER_SIZE*/; if (this.curves.length > size) { - let newCurves = Utils.newFloatArray(size); + const newCurves = Utils.newFloatArray(size); Utils.arrayCopy(this.curves, 0, newCurves, 0, size); this.curves = newCurves; } @@ -313,11 +313,11 @@ export abstract class CurveTimeline extends Timeline { * @param value2 The value for the second key. */ setBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number, cy2: number, time2: number, value2: number) { - let curves = this.curves; + const curves = this.curves; let i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/; - if (value == 0) curves[frame] = 2/*BEZIER*/ + i; - let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; - let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; + if (value === 0) curves[frame] = 2/*BEZIER*/ + i; + const tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + const dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006; let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; let x = time1 + dx, y = value1 + dy; @@ -338,20 +338,20 @@ export abstract class CurveTimeline extends Timeline { * @param valueOffset The offset from frameIndex to the value this curve is used for. * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ getBezierValue (time: number, frameIndex: number, valueOffset: number, i: number) { - let curves = this.curves; + const curves = this.curves; if (curves[i] > time) { - let x = this.frames[frameIndex], y = this.frames[frameIndex + valueOffset]; + const x = this.frames[frameIndex], y = this.frames[frameIndex + valueOffset]; return y + (time - x) / (curves[i] - x) * (curves[i + 1] - y); } - let n = i + 18/*BEZIER_SIZE*/; + const n = i + 18/*BEZIER_SIZE*/; for (i += 2; i < n; i += 2) { if (curves[i] >= time) { - let x = curves[i - 2], y = curves[i - 1]; + const x = curves[i - 2], y = curves[i - 1]; return y + (time - x) / (curves[i] - x) * (curves[i + 1] - y); } } frameIndex += this.getFrameEntries(); - let x = curves[n - 2], y = curves[n - 1]; + const x = curves[n - 2], y = curves[n - 1]; return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); } } @@ -376,7 +376,7 @@ export abstract class CurveTimeline1 extends CurveTimeline { /** Returns the interpolated value for the specified time. */ getCurveValue (time: number) { - let frames = this.frames; + const frames = this.frames; let i = frames.length - 2; for (let ii = 2; ii <= i; ii += 2) { if (frames[ii] > time) { @@ -385,11 +385,12 @@ export abstract class CurveTimeline1 extends CurveTimeline { } } - let curveType = this.curves[i >> 1]; + const curveType = this.curves[i >> 1]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i], value = frames[i + 1/*VALUE*/]; + case 0/*LINEAR*/: { + const before = frames[i], value = frames[i + 1/*VALUE*/]; return value + (time - before) / (frames[i + 2/*ENTRIES*/] - before) * (frames[i + 2/*ENTRIES*/ + 1/*VALUE*/] - value); + } case 1/*STEPPED*/: return frames[i + 1/*VALUE*/]; } @@ -406,12 +407,12 @@ export abstract class CurveTimeline1 extends CurveTimeline { } return current; } - let value = this.getCurveValue(time); + const value = this.getCurveValue(time); switch (blend) { case MixBlend.setup: return setup + value * alpha; case MixBlend.first: case MixBlend.replace: return current + (value + setup - current) * alpha; - case MixBlend.add: return current + value * alpha;; + case MixBlend.add: return current + value * alpha; } } @@ -430,7 +431,7 @@ export abstract class CurveTimeline1 extends CurveTimeline { default: return current; } } - let value = this.getCurveValue(time); + const value = this.getCurveValue(time); switch (blend) { case MixBlend.setup: return setup + (value - setup) * alpha; case MixBlend.first: @@ -464,10 +465,10 @@ export abstract class CurveTimeline1 extends CurveTimeline { default: return current; } } - let value = this.getCurveValue(time) * setup; + const value = this.getCurveValue(time) * setup; if (alpha === 1) return blend === MixBlend.add ? current + value - setup : value; // Mixing out uses sign of setup or current pose, else use sign of key. - if (direction == MixDirection.out) { + if (direction === MixDirection.out) { switch (blend) { case MixBlend.setup: return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; @@ -498,7 +499,7 @@ export abstract class BoneTimeline2 extends CurveTimeline implements BoneTimelin /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. * @param propertyIds Unique identifiers for the properties the timeline modifies. */ constructor (frameCount: number, bezierCount: number, boneIndex: number, property1: Property, property2: Property) { - super(frameCount, bezierCount, property1 + "|" + boneIndex, property2 + "|" + boneIndex); + super(frameCount, bezierCount, `${property1}|${boneIndex}`, `${property2}|${boneIndex}`); this.boneIndex = boneIndex; } @@ -518,7 +519,7 @@ export abstract class BoneTimeline2 extends CurveTimeline implements BoneTimelin apply (skeleton: Skeleton, lastTime: number, time: number, events: Array | null, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean): void { - let bone = skeleton.bones[this.boneIndex]; + const bone = skeleton.bones[this.boneIndex]; if (bone.active) this.apply1(appliedPose ? bone.applied : bone.pose, bone.data.setup, time, alpha, blend, direction); } @@ -531,7 +532,7 @@ export interface BoneTimeline { boneIndex: number; } -export function isBoneTimeline (obj: any): obj is BoneTimeline { +export function isBoneTimeline (obj: Timeline & Partial): obj is Timeline & BoneTimeline { return typeof obj === 'object' && obj !== null && typeof obj.boneIndex === 'number'; } @@ -539,7 +540,7 @@ export abstract class BoneTimeline1 extends CurveTimeline1 implements BoneTimeli readonly boneIndex: number; constructor (frameCount: number, bezierCount: number, boneIndex: number, property: Property) { - super(frameCount, bezierCount, property + "|" + boneIndex); + super(frameCount, bezierCount, `${property}|${boneIndex}`); this.boneIndex = boneIndex; } @@ -572,7 +573,7 @@ export class TranslateTimeline extends BoneTimeline2 { } apply1 (pose: BoneLocal, setup: BoneLocal, time: number, alpha: number, blend: MixBlend, direction: MixDirection) { - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { switch (blend) { case MixBlend.setup: @@ -587,17 +588,18 @@ export class TranslateTimeline extends BoneTimeline2 { } let x = 0, y = 0; - let i = Timeline.search(frames, time, 3/*ENTRIES*/); - let curveType = this.curves[i / 3/*ENTRIES*/]; + const i = Timeline.search(frames, time, 3/*ENTRIES*/); + const curveType = this.curves[i / 3/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; - let t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); x += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t; y += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t; break; + } case 1/*STEPPED*/: x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; @@ -653,7 +655,7 @@ export class ScaleTimeline extends BoneTimeline2 { } protected apply1 (pose: BoneLocal, setup: BoneLocal, time: number, alpha: number, blend: MixBlend, direction: MixDirection) { - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { switch (blend) { case MixBlend.setup: @@ -667,18 +669,19 @@ export class ScaleTimeline extends BoneTimeline2 { return; } - let x, y; - let i = Timeline.search(frames, time, 3/*ENTRIES*/); - let curveType = this.curves[i / 3/*ENTRIES*/]; + let x: number, y: number; + const i = Timeline.search(frames, time, 3/*ENTRIES*/); + const curveType = this.curves[i / 3/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; - let t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); x += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t; y += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t; break; + } case 1/*STEPPED*/: x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; @@ -690,8 +693,8 @@ export class ScaleTimeline extends BoneTimeline2 { x *= setup.scaleX; y *= setup.scaleY; - if (alpha == 1) { - if (blend == MixBlend.add) { + if (alpha === 1) { + if (blend === MixBlend.add) { pose.scaleX += x - setup.scaleX; pose.scaleY += y - setup.scaleY; } else { @@ -700,7 +703,7 @@ export class ScaleTimeline extends BoneTimeline2 { } } else { let bx = 0, by = 0; - if (direction == MixDirection.out) { + if (direction === MixDirection.out) { switch (blend) { case MixBlend.setup: bx = setup.scaleX; @@ -772,7 +775,7 @@ export class ShearTimeline extends BoneTimeline2 { } protected apply1 (pose: BoneLocal, setup: BoneLocal, time: number, alpha: number, blend: MixBlend, direction: MixDirection) { - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { switch (blend) { case MixBlend.setup: @@ -787,17 +790,18 @@ export class ShearTimeline extends BoneTimeline2 { } let x = 0, y = 0; - let i = Timeline.search(frames, time, 3/*ENTRIES*/); - let curveType = this.curves[i / 3/*ENTRIES*/]; + const i = Timeline.search(frames, time, 3/*ENTRIES*/); + const curveType = this.curves[i / 3/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; - let t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 3/*ENTRIES*/] - before); x += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t; y += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t; break; + } case 1/*STEPPED*/: x = frames[i + 1/*VALUE1*/]; y = frames[i + 2/*VALUE2*/]; @@ -851,7 +855,7 @@ export class InheritTimeline extends Timeline implements BoneTimeline { readonly boneIndex: number; constructor (frameCount: number, boneIndex: number) { - super(frameCount, Property.inherit + "|" + boneIndex); + super(frameCount, `${Property.inherit}|${boneIndex}`); this.boneIndex = boneIndex; } @@ -871,7 +875,7 @@ export class InheritTimeline extends Timeline implements BoneTimeline { public apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - let bone = skeleton.bones[this.boneIndex]; + const bone = skeleton.bones[this.boneIndex]; if (!bone.active) return; const pose = appliedPose ? bone.applied : bone.pose; @@ -880,9 +884,9 @@ export class InheritTimeline extends Timeline implements BoneTimeline { return; } - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { - if (blend == MixBlend.setup || blend == MixBlend.first) pose.inherit = bone.data.setup.inherit; + if (blend === MixBlend.setup || blend === MixBlend.first) pose.inherit = bone.data.setup.inherit; } else pose.inherit = this.frames[Timeline.search(frames, time, 2/*ENTRIES*/) + 1/*INHERIT*/]; } @@ -910,8 +914,8 @@ export abstract class SlotCurveTimeline extends CurveTimeline implements SlotTim export class RGBATimeline extends SlotCurveTimeline { constructor (frameCount: number, bezierCount: number, slotIndex: number) { super(frameCount, bezierCount, slotIndex, // - Property.rgb + "|" + slotIndex, // - Property.alpha + "|" + slotIndex); + `${Property.rgb}|${slotIndex}`, // + `${Property.alpha}|${slotIndex}`); } getFrameEntries () { @@ -929,10 +933,10 @@ export class RGBATimeline extends SlotCurveTimeline { } protected apply1 (slot: Slot, pose: SlotPose, time: number, alpha: number, blend: MixBlend) { - let frames = this.frames; - let color = pose.color; + const frames = this.frames; + const color = pose.color; if (time < frames[0]) { - let setup = slot.data.setup.color; + const setup = slot.data.setup.color; switch (blend) { case MixBlend.setup: color.setFromColor(setup); break; case MixBlend.first: color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, @@ -942,21 +946,22 @@ export class RGBATimeline extends SlotCurveTimeline { } let r = 0, g = 0, b = 0, a = 0; - let i = Timeline.search(frames, time, 5/*ENTRIES*/); - let curveType = this.curves[i / 5/*ENTRIES*/]; + const i = Timeline.search(frames, time, 5/*ENTRIES*/); + const curveType = this.curves[i / 5/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; b = frames[i + 3/*B*/]; a = frames[i + 4/*A*/]; - let t = (time - before) / (frames[i + 5/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 5/*ENTRIES*/] - before); r += (frames[i + 5/*ENTRIES*/ + 1/*R*/] - r) * t; g += (frames[i + 5/*ENTRIES*/ + 2/*G*/] - g) * t; b += (frames[i + 5/*ENTRIES*/ + 3/*B*/] - b) * t; a += (frames[i + 5/*ENTRIES*/ + 4/*A*/] - a) * t; break; + } case 1/*STEPPED*/: r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; @@ -969,10 +974,10 @@ export class RGBATimeline extends SlotCurveTimeline { b = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/); a = this.getBezierValue(time, i, 4/*A*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/); } - if (alpha == 1) + if (alpha === 1) color.set(r, g, b, a); else { - if (blend == MixBlend.setup) color.setFromColor(slot.data.setup.color); + if (blend === MixBlend.setup) color.setFromColor(slot.data.setup.color); color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); } } @@ -981,7 +986,7 @@ export class RGBATimeline extends SlotCurveTimeline { /** Changes the RGB for a slot's {@link SlotPose.color}. */ export class RGBTimeline extends SlotCurveTimeline { constructor (frameCount: number, bezierCount: number, slotIndex: number) { - super(frameCount, bezierCount, slotIndex, Property.rgb + "|" + slotIndex); + super(frameCount, bezierCount, slotIndex, `${Property.rgb}|${slotIndex}`); } getFrameEntries () { @@ -998,10 +1003,10 @@ export class RGBTimeline extends SlotCurveTimeline { } protected apply1 (slot: Slot, pose: SlotPose, time: number, alpha: number, blend: MixBlend) { - let frames = this.frames; - let color = pose.color; + const frames = this.frames; + const color = pose.color; if (time < frames[0]) { - let setup = slot.data.setup.color; + const setup = slot.data.setup.color; switch (blend) { case MixBlend.setup: color.r = setup.r; @@ -1017,19 +1022,20 @@ export class RGBTimeline extends SlotCurveTimeline { } let r = 0, g = 0, b = 0; - let i = Timeline.search(frames, time, 4/*ENTRIES*/); - let curveType = this.curves[i >> 2]; + const i = Timeline.search(frames, time, 4/*ENTRIES*/); + const curveType = this.curves[i >> 2]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; b = frames[i + 3/*B*/]; - let t = (time - before) / (frames[i + 4/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 4/*ENTRIES*/] - before); r += (frames[i + 4/*ENTRIES*/ + 1/*R*/] - r) * t; g += (frames[i + 4/*ENTRIES*/ + 2/*G*/] - g) * t; b += (frames[i + 4/*ENTRIES*/ + 3/*B*/] - b) * t; break; + } case 1/*STEPPED*/: r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; @@ -1040,13 +1046,13 @@ export class RGBTimeline extends SlotCurveTimeline { g = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/); b = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/); } - if (alpha == 1) { + if (alpha === 1) { color.r = r; color.g = g; color.b = b; } else { - if (blend == MixBlend.setup) { - let setup = slot.data.setup.color; + if (blend === MixBlend.setup) { + const setup = slot.data.setup.color; color.r = setup.r; color.g = setup.g; color.b = setup.b; @@ -1063,20 +1069,20 @@ export class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { slotIndex = 0; constructor (frameCount: number, bezierCount: number, slotIndex: number) { - super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + super(frameCount, bezierCount, `${Property.alpha}|${slotIndex}`); this.slotIndex = slotIndex; } apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - let slot = skeleton.slots[this.slotIndex]; + const slot = skeleton.slots[this.slotIndex]; if (!slot.bone.active) return; const color = (appliedPose ? slot.applied : slot.pose).color; const frames = this.frames; - if (time < this.frames[0]) { - let setup = slot.data.setup.color; + if (time < frames[0]) { + const setup = slot.data.setup.color; switch (blend) { case MixBlend.setup: color.a = setup.a; break; case MixBlend.first: color.a += (setup.a - color.a) * alpha; break; @@ -1084,11 +1090,11 @@ export class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { return; } - let a = this.getCurveValue(time); - if (alpha == 1) + const a = this.getCurveValue(time); + if (alpha === 1) color.a = a; else { - if (blend == MixBlend.setup) color.a = slot.data.setup.color.a; + if (blend === MixBlend.setup) color.a = slot.data.setup.color.a; color.a += (a - color.a) * alpha; } } @@ -1098,9 +1104,9 @@ export class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { export class RGBA2Timeline extends SlotCurveTimeline { constructor (frameCount: number, bezierCount: number, slotIndex: number) { super(frameCount, bezierCount, slotIndex, // - Property.rgb + "|" + slotIndex, // - Property.alpha + "|" + slotIndex, // - Property.rgb2 + "|" + slotIndex); + `${Property.rgb}|${slotIndex}`, // + `${Property.alpha}|${slotIndex}`, // + `${Property.rgb2}|${slotIndex}`); } getFrameEntries () { @@ -1122,9 +1128,11 @@ export class RGBA2Timeline extends SlotCurveTimeline { protected apply1 (slot: Slot, pose: SlotPose, time: number, alpha: number, blend: MixBlend) { const frames = this.frames; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime const light = pose.color, dark = pose.darkColor!; if (time < frames[0]) { const setup = slot.data.setup; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime const setupLight = setup.color, setupDark = setup.darkColor!; switch (blend) { case MixBlend.setup: @@ -1144,11 +1152,11 @@ export class RGBA2Timeline extends SlotCurveTimeline { } let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; - let i = Timeline.search(frames, time, 8/*ENTRIES*/); - let curveType = this.curves[i >> 3]; + const i = Timeline.search(frames, time, 8/*ENTRIES*/); + const curveType = this.curves[i >> 3]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; b = frames[i + 3/*B*/]; @@ -1156,7 +1164,7 @@ export class RGBA2Timeline extends SlotCurveTimeline { r2 = frames[i + 5/*R2*/]; g2 = frames[i + 6/*G2*/]; b2 = frames[i + 7/*B2*/]; - let t = (time - before) / (frames[i + 8/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 8/*ENTRIES*/] - before); r += (frames[i + 8/*ENTRIES*/ + 1/*R*/] - r) * t; g += (frames[i + 8/*ENTRIES*/ + 2/*G*/] - g) * t; b += (frames[i + 8/*ENTRIES*/ + 3/*B*/] - b) * t; @@ -1165,6 +1173,7 @@ export class RGBA2Timeline extends SlotCurveTimeline { g2 += (frames[i + 8/*ENTRIES*/ + 6/*G2*/] - g2) * t; b2 += (frames[i + 8/*ENTRIES*/ + 7/*B2*/] - b2) * t; break; + } case 1/*STEPPED*/: r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; @@ -1184,16 +1193,17 @@ export class RGBA2Timeline extends SlotCurveTimeline { b2 = this.getBezierValue(time, i, 7/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 6 - 2/*BEZIER*/); } - if (alpha == 1) { + if (alpha === 1) { light.set(r, g, b, a); dark.r = r2; dark.g = g2; dark.b = b2; } else { - if (blend == MixBlend.setup) { + if (blend === MixBlend.setup) { const setup = slot.data.setup; light.setFromColor(setup.color); - let setupDark = setup.darkColor!; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime + const setupDark = setup.darkColor!; dark.r = setupDark.r; dark.g = setupDark.g; dark.b = setupDark.b; @@ -1210,8 +1220,8 @@ export class RGBA2Timeline extends SlotCurveTimeline { export class RGB2Timeline extends SlotCurveTimeline { constructor (frameCount: number, bezierCount: number, slotIndex: number) { super(frameCount, bezierCount, slotIndex, // - Property.rgb + "|" + slotIndex, // - Property.rgb2 + "|" + slotIndex); + `${Property.rgb}|${slotIndex}`, // + `${Property.rgb2}|${slotIndex}`); } getFrameEntries () { @@ -1232,9 +1242,11 @@ export class RGB2Timeline extends SlotCurveTimeline { protected apply1 (slot: Slot, pose: SlotPose, time: number, alpha: number, blend: MixBlend) { const frames = this.frames; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime const light = pose.color, dark = pose.darkColor!; if (time < frames[0]) { const setup = slot.data.setup; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime const setupLight = setup.color, setupDark = setup.darkColor!; switch (blend) { case MixBlend.setup: @@ -1256,19 +1268,19 @@ export class RGB2Timeline extends SlotCurveTimeline { return; } - let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; - let i = Timeline.search(frames, time, 7/*ENTRIES*/); - let curveType = this.curves[i / 7/*ENTRIES*/]; + let r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0; + const i = Timeline.search(frames, time, 7/*ENTRIES*/); + const curveType = this.curves[i / 7/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; b = frames[i + 3/*B*/]; r2 = frames[i + 4/*R2*/]; g2 = frames[i + 5/*G2*/]; b2 = frames[i + 6/*B2*/]; - let t = (time - before) / (frames[i + 7/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 7/*ENTRIES*/] - before); r += (frames[i + 7/*ENTRIES*/ + 1/*R*/] - r) * t; g += (frames[i + 7/*ENTRIES*/ + 2/*G*/] - g) * t; b += (frames[i + 7/*ENTRIES*/ + 3/*B*/] - b) * t; @@ -1276,6 +1288,7 @@ export class RGB2Timeline extends SlotCurveTimeline { g2 += (frames[i + 7/*ENTRIES*/ + 5/*G2*/] - g2) * t; b2 += (frames[i + 7/*ENTRIES*/ + 6/*B2*/] - b2) * t; break; + } case 1/*STEPPED*/: r = frames[i + 1/*R*/]; g = frames[i + 2/*G*/]; @@ -1293,7 +1306,7 @@ export class RGB2Timeline extends SlotCurveTimeline { b2 = this.getBezierValue(time, i, 6/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/); } - if (alpha == 1) { + if (alpha === 1) { light.r = r; light.g = g; light.b = b; @@ -1301,8 +1314,9 @@ export class RGB2Timeline extends SlotCurveTimeline { dark.g = g2; dark.b = b2; } else { - if (blend == MixBlend.setup) { + if (blend === MixBlend.setup) { const setup = slot.data.setup; + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime const setupLight = setup.color, setupDark = setup.darkColor!; light.r = setupLight.r; light.g = setupLight.g; @@ -1329,7 +1343,7 @@ export class AttachmentTimeline extends Timeline implements SlotTimeline { attachmentNames: Array; constructor (frameCount: number, slotIndex: number) { - super(frameCount, Property.attachment + "|" + slotIndex); + super(frameCount, `${Property.attachment}|${slotIndex}`); this.slotIndex = slotIndex; this.attachmentNames = new Array(frameCount); } @@ -1347,14 +1361,14 @@ export class AttachmentTimeline extends Timeline implements SlotTimeline { apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - let slot = skeleton.slots[this.slotIndex]; + const slot = skeleton.slots[this.slotIndex]; if (!slot.bone.active) return; const pose = appliedPose ? slot.applied : slot.pose; - if (direction == MixDirection.out) { - if (blend == MixBlend.setup) this.setAttachment(skeleton, pose, slot.data.attachmentName); + if (direction === MixDirection.out) { + if (blend === MixBlend.setup) this.setAttachment(skeleton, pose, slot.data.attachmentName); } else if (time < this.frames[0]) { - if (blend == MixBlend.setup || blend == MixBlend.first) this.setAttachment(skeleton, pose, slot.data.attachmentName); + if (blend === MixBlend.setup || blend === MixBlend.first) this.setAttachment(skeleton, pose, slot.data.attachmentName); } else this.setAttachment(skeleton, pose, this.attachmentNames[Timeline.search(this.frames, time)]); } @@ -1375,7 +1389,7 @@ export class DeformTimeline extends SlotCurveTimeline { vertices: Array; constructor (frameCount: number, bezierCount: number, slotIndex: number, attachment: VertexAttachment) { - super(frameCount, bezierCount, slotIndex, Property.deform + "|" + slotIndex + "|" + attachment.id); + super(frameCount, bezierCount, slotIndex, `${Property.deform}|${slotIndex}|${attachment.id}`); this.attachment = attachment; this.vertices = new Array(frameCount); } @@ -1397,11 +1411,11 @@ export class DeformTimeline extends SlotCurveTimeline { * @param value2 Ignored (1 is used for a deform timeline). */ setBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number, cy2: number, time2: number, value2: number) { - let curves = this.curves; + const curves = this.curves; let i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/; - if (value == 0) curves[frame] = 2/*BEZIER*/ + i; - let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; - let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + if (value === 0) curves[frame] = 2/*BEZIER*/ + i; + const tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + const dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018; let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; let x = time1 + dx, y = dy; @@ -1418,61 +1432,62 @@ export class DeformTimeline extends SlotCurveTimeline { } getCurvePercent (time: number, frame: number) { - let curves = this.curves; + const curves = this.curves; let i = curves[frame]; switch (i) { - case 0/*LINEAR*/: - let x = this.frames[frame]; + case 0/*LINEAR*/: { + const x = this.frames[frame]; return (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } case 1/*STEPPED*/: return 0; } i -= 2/*BEZIER*/; if (curves[i] > time) { - let x = this.frames[frame]; + const x = this.frames[frame]; return curves[i + 1] * (time - x) / (curves[i] - x); } - let n = i + 18/*BEZIER_SIZE*/; + const n = i + 18/*BEZIER_SIZE*/; for (i += 2; i < n; i += 2) { if (curves[i] >= time) { - let x = curves[i - 2], y = curves[i - 1]; + const x = curves[i - 2], y = curves[i - 1]; return y + (time - x) / (curves[i] - x) * (curves[i + 1] - y); } } - let x = curves[n - 2], y = curves[n - 1]; + const x = curves[n - 2], y = curves[n - 1]; return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); } protected apply1 (slot: Slot, pose: SlotPose, time: number, alpha: number, blend: MixBlend) { if (!(pose.attachment instanceof VertexAttachment)) return; - let vertexAttachment = pose.attachment; - if (vertexAttachment.timelineAttachment != this.attachment) return; + const vertexAttachment = pose.attachment; + if (vertexAttachment.timelineAttachment !== this.attachment) return; - let deform = pose.deform; - if (deform.length == 0) blend = MixBlend.setup; + const deform = pose.deform; + if (deform.length === 0) blend = MixBlend.setup; - let vertices = this.vertices; - let vertexCount = vertices[0].length; + const vertices = this.vertices; + const vertexCount = vertices[0].length; - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { switch (blend) { case MixBlend.setup: deform.length = 0; return; case MixBlend.first: - if (alpha == 1) { + if (alpha === 1) { deform.length = 0; return; } deform.length = vertexCount; if (!vertexAttachment.bones) { // Unweighted vertex positions. - let setupVertices = vertexAttachment.vertices; - for (var i = 0; i < vertexCount; i++) + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) deform[i] += (setupVertices[i] - deform[i]) * alpha; } else { // Weighted deform offsets. alpha = 1 - alpha; - for (var i = 0; i < vertexCount; i++) + for (let i = 0; i < vertexCount; i++) deform[i] *= alpha; } } @@ -1481,11 +1496,11 @@ export class DeformTimeline extends SlotCurveTimeline { deform.length = vertexCount; if (time >= frames[frames.length - 1]) { // Time is after last frame. - let lastVertices = vertices[frames.length - 1]; - if (alpha == 1) { - if (blend == MixBlend.add) { + const lastVertices = vertices[frames.length - 1]; + if (alpha === 1) { + if (blend === MixBlend.add) { if (!vertexAttachment.bones) { // Unweighted vertex positions, no alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) deform[i] += lastVertices[i] - setupVertices[i]; } else { // Weighted deform offsets, no alpha. @@ -1498,9 +1513,9 @@ export class DeformTimeline extends SlotCurveTimeline { switch (blend) { case MixBlend.setup: { if (!vertexAttachment.bones) { // Unweighted vertex positions, with alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) { - let setup = setupVertices[i]; + const setup = setupVertices[i]; deform[i] = setup + (lastVertices[i] - setup) * alpha; } } else { // Weighted deform offsets, with alpha. @@ -1516,7 +1531,7 @@ export class DeformTimeline extends SlotCurveTimeline { break; case MixBlend.add: if (!vertexAttachment.bones) { // Unweighted vertex positions, no alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; } else { // Weighted deform offsets, alpha. @@ -1528,22 +1543,22 @@ export class DeformTimeline extends SlotCurveTimeline { return; } - let frame = Timeline.search(frames, time); - let percent = this.getCurvePercent(time, frame); - let prevVertices = vertices[frame]; - let nextVertices = vertices[frame + 1]; + const frame = Timeline.search(frames, time); + const percent = this.getCurvePercent(time, frame); + const prevVertices = vertices[frame]; + const nextVertices = vertices[frame + 1]; - if (alpha == 1) { - if (blend == MixBlend.add) { + if (alpha === 1) { + if (blend === MixBlend.add) { if (!vertexAttachment.bones) { // Unweighted vertex positions, no alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; } } else { // Weighted deform offsets, no alpha. for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] += prev + (nextVertices[i] - prev) * percent; } } @@ -1551,7 +1566,7 @@ export class DeformTimeline extends SlotCurveTimeline { Utils.arrayCopy(prevVertices, 0, deform, 0, vertexCount) else { // Vertex positions or deform offsets, no alpha. for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] = prev + (nextVertices[i] - prev) * percent; } } @@ -1559,14 +1574,14 @@ export class DeformTimeline extends SlotCurveTimeline { switch (blend) { case MixBlend.setup: { if (!vertexAttachment.bones) { // Unweighted vertex positions, with alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i], setup = setupVertices[i]; + const prev = prevVertices[i], setup = setupVertices[i]; deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; } } else { // Weighted deform offsets, with alpha. for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; } } @@ -1575,20 +1590,20 @@ export class DeformTimeline extends SlotCurveTimeline { case MixBlend.first: case MixBlend.replace: // Vertex positions or deform offsets, with alpha. for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; } break; case MixBlend.add: if (!vertexAttachment.bones) { // Unweighted vertex positions, with alpha. - let setupVertices = vertexAttachment.vertices; + const setupVertices = vertexAttachment.vertices; for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; } } else { // Weighted deform offsets, with alpha. for (let i = 0; i < vertexCount; i++) { - let prev = prevVertices[i]; + const prev = prevVertices[i]; deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; } } @@ -1607,8 +1622,8 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { readonly attachment: HasTextureRegion; constructor (frameCount: number, slotIndex: number, attachment: HasTextureRegion) { - super(frameCount, - Property.sequence + "|" + slotIndex + "|" + attachment.sequence!.id); + // biome-ignore lint/style/noNonNullAssertion: expected behavior from reference runtime + super(frameCount, `${Property.sequence}|${slotIndex}|${attachment.sequence!.id}`); this.slotIndex = slotIndex; this.attachment = attachment; } @@ -1629,7 +1644,7 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { * @param frame Between 0 and frameCount, inclusive. * @param time Seconds between frames. */ setFrame (frame: number, time: number, mode: SequenceMode, index: number, delay: number) { - let frames = this.frames; + const frames = this.frames; frame *= SequenceTimeline.ENTRIES; frames[frame] = time; frames[frame + SequenceTimeline.MODE] = mode | (index << 4); @@ -1639,12 +1654,12 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - let slot = skeleton.slots[this.slotIndex]; + const slot = skeleton.slots[this.slotIndex]; if (!slot.bone.active) return; const pose = appliedPose ? slot.applied : slot.pose; - let slotAttachment = pose.attachment; - let attachment = this.attachment as unknown as Attachment; + const slotAttachment = pose.attachment; + const attachment = this.attachment as unknown as Attachment; if (slotAttachment !== attachment) { if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment !== attachment) return; @@ -1658,7 +1673,7 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { return; } - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { if (blend === MixBlend.setup || blend === MixBlend.first) pose.sequenceIndex = -1; return; @@ -1677,7 +1692,7 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { case SequenceMode.once: index = Math.min(count - 1, index); break; case SequenceMode.loop: index %= count; break; case SequenceMode.pingpong: { - let n = (count << 1) - 2; + const n = (count << 1) - 2; index = n === 0 ? 0 : index % n; if (index >= count) index = n - index; break; @@ -1685,8 +1700,8 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { case SequenceMode.onceReverse: index = Math.max(count - 1 - index, 0); break; case SequenceMode.loopReverse: index = count - 1 - (index % count); break; case SequenceMode.pingpongReverse: { - let n = (count << 1) - 2; - index = n == 0 ? 0 : (index + count - 1) % n; + const n = (count << 1) - 2; + index = n === 0 ? 0 : (index + count - 1) % n; if (index >= count) index = n - index; } } @@ -1697,7 +1712,7 @@ export class SequenceTimeline extends Timeline implements SlotTimeline { /** Fires an {@link Event} when specific animation times are reached. */ export class EventTimeline extends Timeline { - static propertyIds = ["" + Property.event]; + static propertyIds = [`${Property.event}`]; /** The event for each key frame. */ events: Array; @@ -1724,8 +1739,8 @@ export class EventTimeline extends Timeline { if (!firedEvents) return; - let frames = this.frames; - let frameCount = this.frames.length; + const frames = this.frames; + const frameCount = this.frames.length; if (lastTime > time) { // Apply after lastTime for looped animations. this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction, appliedPose); @@ -1739,9 +1754,9 @@ export class EventTimeline extends Timeline { i = 0; else { i = Timeline.search(frames, lastTime) + 1; - let frameTime = frames[i]; + const frameTime = frames[i]; while (i > 0) { // Fire multiple events with the same frame. - if (frames[i - 1] != frameTime) break; + if (frames[i - 1] !== frameTime) break; i--; } } @@ -1752,7 +1767,7 @@ export class EventTimeline extends Timeline { /** Changes a skeleton's {@link Skeleton#drawOrder}. */ export class DrawOrderTimeline extends Timeline { - static propertyIds = ["" + Property.drawOrder]; + static propertyIds = [`${Property.drawOrder}`]; /** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */ drawOrders: Array | null>; @@ -1777,23 +1792,23 @@ export class DrawOrderTimeline extends Timeline { apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - if (direction == MixDirection.out) { - if (blend == MixBlend.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + if (direction === MixDirection.out) { + if (blend === MixBlend.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } if (time < this.frames[0]) { - if (blend == MixBlend.setup || blend == MixBlend.first) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + if (blend === MixBlend.setup || blend === MixBlend.first) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } - let idx = Timeline.search(this.frames, time); - let drawOrderToSetupIndex = this.drawOrders[idx]; + const idx = Timeline.search(this.frames, time); + const drawOrderToSetupIndex = this.drawOrders[idx]; if (!drawOrderToSetupIndex) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); else { - let drawOrder: Array = skeleton.drawOrder; - let slots: Array = skeleton.slots; + const drawOrder: Array = skeleton.drawOrder; + const slots: Array = skeleton.slots; for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) drawOrder[i] = slots[drawOrderToSetupIndex[i]]; } @@ -1806,7 +1821,7 @@ export interface ConstraintTimeline { readonly constraintIndex: number; } -export function isConstraintTimeline (obj: any): obj is ConstraintTimeline { +export function isConstraintTimeline (obj: Timeline & Partial): obj is Timeline & ConstraintTimeline { return typeof obj === 'object' && obj !== null && typeof obj.constraintIndex === 'number'; } @@ -1817,7 +1832,7 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim readonly constraintIndex: number = 0; constructor (frameCount: number, bezierCount: number, constraintIndex: number) { - super(frameCount, bezierCount, Property.ikConstraint + "|" + constraintIndex); + super(frameCount, bezierCount, `${Property.ikConstraint}|${constraintIndex}`); this.constraintIndex = constraintIndex; } @@ -1846,7 +1861,7 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim if (!constraint.active) return; const pose = appliedPose ? constraint.applied : constraint.pose; - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { const setup = constraint.data.setup; switch (blend) { @@ -1868,17 +1883,18 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim } let mix = 0, softness = 0; - let i = Timeline.search(frames, time, 6/*ENTRIES*/) - let curveType = this.curves[i / 6/*ENTRIES*/]; + const i = Timeline.search(frames, time, 6/*ENTRIES*/) + const curveType = this.curves[i / 6/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; mix = frames[i + 1/*MIX*/]; softness = frames[i + 2/*SOFTNESS*/]; - let t = (time - before) / (frames[i + 6/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 6/*ENTRIES*/] - before); mix += (frames[i + 6/*ENTRIES*/ + 1/*MIX*/] - mix) * t; softness += (frames[i + 6/*ENTRIES*/ + 2/*SOFTNESS*/] - softness) * t; break; + } case 1/*STEPPED*/: mix = frames[i + 1/*MIX*/]; softness = frames[i + 2/*SOFTNESS*/]; @@ -1889,7 +1905,7 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim } switch (blend) { - case MixBlend.setup: + case MixBlend.setup: { const setup = constraint.data.setup; pose.mix = setup.mix + (mix - setup.mix) * alpha; pose.softness = setup.softness + (softness - setup.softness) * alpha; @@ -1900,6 +1916,7 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim return; } break; + } case MixBlend.first: case MixBlend.replace: pose.mix += (mix - pose.mix) * alpha; @@ -1913,8 +1930,8 @@ export class IkConstraintTimeline extends CurveTimeline implements ConstraintTim break; } pose.bendDirection = frames[i + 3/*BEND_DIRECTION*/]; - pose.compress = frames[i + 4/*COMPRESS*/] != 0; - pose.stretch = frames[i + 5/*STRETCH*/] != 0; + pose.compress = frames[i + 4/*COMPRESS*/] !== 0; + pose.stretch = frames[i + 5/*STRETCH*/] !== 0; } } @@ -1926,7 +1943,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr constraintIndex: number = 0; constructor (frameCount: number, bezierCount: number, constraintIndex: number) { - super(frameCount, bezierCount, Property.transformConstraint + "|" + constraintIndex); + super(frameCount, bezierCount, `${Property.transformConstraint}|${constraintIndex}`); this.constraintIndex = constraintIndex; } @@ -1939,7 +1956,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr * @param time The frame time in seconds. */ setFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number, mixScaleX: number, mixScaleY: number, mixShearY: number) { - let frames = this.frames; + const frames = this.frames; frame *= 7/*ENTRIES*/; frames[frame] = time; frames[frame + 1/*ROTATE*/] = mixRotate; @@ -1957,7 +1974,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr if (!constraint.active) return; const pose = appliedPose ? constraint.applied : constraint.pose; - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { const setup = constraint.data.setup; switch (blend) { @@ -1980,19 +1997,19 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr return; } - let rotate, x, y, scaleX, scaleY, shearY; - let i = Timeline.search(frames, time, 7/*ENTRIES*/); - let curveType = this.curves[i / 7/*ENTRIES*/]; + let rotate: number, x: number, y: number, scaleX: number, scaleY: number, shearY: number; + const i = Timeline.search(frames, time, 7/*ENTRIES*/); + const curveType = this.curves[i / 7/*ENTRIES*/]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; rotate = frames[i + 1/*ROTATE*/]; x = frames[i + 2/*X*/]; y = frames[i + 3/*Y*/]; scaleX = frames[i + 4/*SCALEX*/]; scaleY = frames[i + 5/*SCALEY*/]; shearY = frames[i + 6/*SHEARY*/]; - let t = (time - before) / (frames[i + 7/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 7/*ENTRIES*/] - before); rotate += (frames[i + 7/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t; x += (frames[i + 7/*ENTRIES*/ + 2/*X*/] - x) * t; y += (frames[i + 7/*ENTRIES*/ + 3/*Y*/] - y) * t; @@ -2000,6 +2017,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr scaleY += (frames[i + 7/*ENTRIES*/ + 5/*SCALEY*/] - scaleY) * t; shearY += (frames[i + 7/*ENTRIES*/ + 6/*SHEARY*/] - shearY) * t; break; + } case 1/*STEPPED*/: rotate = frames[i + 1/*ROTATE*/]; x = frames[i + 2/*X*/]; @@ -2018,7 +2036,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr } switch (blend) { - case MixBlend.setup: + case MixBlend.setup: { const setup = constraint.data.setup; pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha; pose.mixX = setup.mixX + (x - setup.mixX) * alpha; @@ -2027,6 +2045,7 @@ export class TransformConstraintTimeline extends CurveTimeline implements Constr pose.mixScaleY = setup.mixScaleY + (scaleY - setup.mixScaleY) * alpha; pose.mixShearY = setup.mixShearY + (shearY - setup.mixShearY) * alpha; break; + } case MixBlend.first: case MixBlend.replace: pose.mixRotate += (rotate - pose.mixRotate) * alpha; @@ -2052,7 +2071,7 @@ export abstract class ConstraintTimeline1 extends CurveTimeline1 implements Cons readonly constraintIndex: number; constructor (frameCount: number, bezierCount: number, constraintIndex: number, property: Property) { - super(frameCount, bezierCount, property + "|" + constraintIndex); + super(frameCount, bezierCount, `${property}|${constraintIndex}`); this.constraintIndex = constraintIndex; } } @@ -2097,7 +2116,7 @@ export class PathConstraintMixTimeline extends CurveTimeline implements Constrai readonly constraintIndex: number; constructor (frameCount: number, bezierCount: number, constraintIndex: number) { - super(frameCount, bezierCount, Property.pathConstraintMix + "|" + constraintIndex); + super(frameCount, bezierCount, `${Property.pathConstraintMix}|${constraintIndex}`); this.constraintIndex = constraintIndex; } @@ -2109,7 +2128,7 @@ export class PathConstraintMixTimeline extends CurveTimeline implements Constrai * @param frame Between 0 and frameCount, inclusive. * @param time The frame time in seconds. */ setFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number) { - let frames = this.frames; + const frames = this.frames; frame <<= 2; frames[frame] = time; frames[frame + 1/*ROTATE*/] = mixRotate; @@ -2124,7 +2143,7 @@ export class PathConstraintMixTimeline extends CurveTimeline implements Constrai if (!constraint.active) return; const pose = appliedPose ? constraint.applied : constraint.pose; - let frames = this.frames; + const frames = this.frames; if (time < frames[0]) { const setup = constraint.data.setup; switch (blend) { @@ -2141,20 +2160,21 @@ export class PathConstraintMixTimeline extends CurveTimeline implements Constrai return; } - let rotate, x, y; - let i = Timeline.search(frames, time, 4/*ENTRIES*/); - let curveType = this.curves[i >> 2]; + let rotate: number, x: number, y: number; + const i = Timeline.search(frames, time, 4/*ENTRIES*/); + const curveType = this.curves[i >> 2]; switch (curveType) { - case 0/*LINEAR*/: - let before = frames[i]; + case 0/*LINEAR*/: { + const before = frames[i]; rotate = frames[i + 1/*ROTATE*/]; x = frames[i + 2/*X*/]; y = frames[i + 3/*Y*/]; - let t = (time - before) / (frames[i + 4/*ENTRIES*/] - before); + const t = (time - before) / (frames[i + 4/*ENTRIES*/] - before); rotate += (frames[i + 4/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t; x += (frames[i + 4/*ENTRIES*/ + 2/*X*/] - x) * t; y += (frames[i + 4/*ENTRIES*/ + 3/*Y*/] - y) * t; break; + } case 1/*STEPPED*/: rotate = frames[i + 1/*ROTATE*/]; x = frames[i + 2/*X*/]; @@ -2167,12 +2187,13 @@ export class PathConstraintMixTimeline extends CurveTimeline implements Constrai } switch (blend) { - case MixBlend.setup: + case MixBlend.setup: { const setup = constraint.data.setup; pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha; pose.mixX = setup.mixX + (x - setup.mixX) * alpha; pose.mixY = setup.mixY + (y - setup.mixY) * alpha; break; + } case MixBlend.first: case MixBlend.replace: pose.mixRotate += (rotate - pose.mixRotate) * alpha; @@ -2198,7 +2219,7 @@ export abstract class PhysicsConstraintTimeline extends ConstraintTimeline1 { apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection, appliedPose: boolean) { - if (this.constraintIndex == -1) { + if (this.constraintIndex === -1) { const value = time >= this.frames[0] ? this.getCurveValue(time) : 0; const constraints = skeleton.physics; for (const constraint of constraints) { diff --git a/spine-ts/spine-core/src/AnimationState.ts b/spine-ts/spine-core/src/AnimationState.ts index ddb011c38..19dc89d96 100644 --- a/spine-ts/spine-core/src/AnimationState.ts +++ b/spine-ts/spine-core/src/AnimationState.ts @@ -27,12 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation, MixBlend, AttachmentTimeline, MixDirection, RotateTimeline, DrawOrderTimeline, Timeline, EventTimeline } from "./Animation.js"; -import { AnimationStateData } from "./AnimationStateData.js"; -import { Skeleton } from "./Skeleton.js"; -import { Slot } from "./Slot.js"; -import { StringSet, Pool, Utils, MathUtils } from "./Utils.js"; -import { Event } from "./Event.js"; +/** biome-ignore-all lint/style/noNonNullAssertion: reference runtime expects some nullable to not be null */ + +import { Animation, AttachmentTimeline, DrawOrderTimeline, EventTimeline, MixBlend, MixDirection, RotateTimeline, Timeline } from "./Animation.js"; +import type { AnimationStateData } from "./AnimationStateData.js"; +import type { Event } from "./Event.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Slot } from "./Slot.js"; +import { MathUtils, Pool, StringSet, Utils } from "./Utils.js"; /** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies @@ -46,7 +48,7 @@ export class AnimationState { data: AnimationStateData; /** The list of tracks that currently have animations, which may contain null entries. */ - readonly tracks = new Array(); + readonly tracks = [] as (TrackEntry | null)[]; /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower * or faster. Defaults to 1. @@ -55,8 +57,8 @@ export class AnimationState { timeScale = 1; unkeyedState = 0; - readonly events = new Array(); - readonly listeners = new Array(); + readonly events = [] as Event[]; + readonly listeners = [] as AnimationStateListener[]; queue = new EventQueue(this); propertyIDs = new StringSet(); animationsChanged = false; @@ -70,9 +72,9 @@ export class AnimationState { /** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */ update (delta: number) { delta *= this.timeScale; - let tracks = this.tracks; + const tracks = this.tracks; for (let i = 0, n = tracks.length; i < n; i++) { - let current = tracks[i]; + const current = tracks[i]; if (!current) continue; current.animationLast = current.nextAnimationLast; @@ -90,10 +92,10 @@ export class AnimationState { let next = current.next; if (next) { // When the next entry's delay is passed, change to the next entry, preserving leftover time. - let nextTime = current.trackLast - next.delay; + const nextTime = current.trackLast - next.delay; if (nextTime >= 0) { next.delay = 0; - next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + next.trackTime += current.timeScale === 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; current.trackTime += currentDelta; this.setCurrent(i, next, true); while (next.mixingFrom) { @@ -127,18 +129,18 @@ export class AnimationState { /** Returns true when all mixing from entries are complete. */ updateMixingFrom (to: TrackEntry, delta: number): boolean { - let from = to.mixingFrom; + const from = to.mixingFrom; if (!from) return true; - let finished = this.updateMixingFrom(from, delta); + const finished = this.updateMixingFrom(from, delta); from.animationLast = from.nextAnimationLast; from.trackLast = from.nextTrackLast; // The from entry was applied at least once and the mix is complete. - if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) { + if (to.nextTrackLast !== -1 && to.mixTime >= to.mixDuration) { // Mixing is complete for all entries before the from entry or the mix is instantaneous. - if (from.totalAlpha == 0 || to.mixDuration == 0) { + if (from.totalAlpha === 0 || to.mixDuration === 0) { to.mixingFrom = from.mixingFrom; if (from.mixingFrom != null) from.mixingFrom.mixingTo = to; to.interruptAlpha = from.interruptAlpha; @@ -159,15 +161,15 @@ export class AnimationState { if (!skeleton) throw new Error("skeleton cannot be null."); if (this.animationsChanged) this._animationsChanged(); - let events = this.events; - let tracks = this.tracks; + const events = this.events; + const tracks = this.tracks; let applied = false; for (let i = 0, n = tracks.length; i < n; i++) { - let current = tracks[i]; + const current = tracks[i]; if (!current || current.delay > 0) continue; applied = true; - let blend: MixBlend = i == 0 ? MixBlend.first : current.mixBlend; + const blend: MixBlend = i === 0 ? MixBlend.first : current.mixBlend; // Apply mixing from entries first. let alpha = current.alpha; @@ -185,10 +187,10 @@ export class AnimationState { applyTime = current.animation!.duration - applyTime; applyEvents = null; } - let timelines = current.animation!.timelines; - let timelineCount = timelines.length; - if ((i == 0 && alpha == 1) || blend == MixBlend.add) { - if (i == 0) attachments = true; + const timelines = current.animation!.timelines; + const timelineCount = timelines.length; + if ((i === 0 && alpha === 1) || blend === MixBlend.add) { + if (i === 0) attachments = true; for (let ii = 0; ii < timelineCount; ii++) { // Fixes issue #302 on IOS9 where mix, blend sometimes became undefined and caused assets // to sometimes stop rendering when using color correction, as their RGBA values become NaN. @@ -201,15 +203,15 @@ export class AnimationState { timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.in, false); } } else { - let timelineMode = current.timelineMode; + const timelineMode = current.timelineMode; - let shortestRotation = current.shortestRotation; - let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1; + const shortestRotation = current.shortestRotation; + const firstFrame = !shortestRotation && current.timelinesRotation.length !== timelineCount << 1; if (firstFrame) current.timelinesRotation.length = timelineCount << 1; for (let ii = 0; ii < timelineCount; ii++) { - let timeline = timelines[ii]; - let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup; + const timeline = timelines[ii]; + const timelineBlend = timelineMode[ii] === SUBSEQUENT ? blend : MixBlend.setup; if (!shortestRotation && timeline instanceof RotateTimeline) { this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); } else if (timeline instanceof AttachmentTimeline) { @@ -234,7 +236,7 @@ export class AnimationState { const slots = skeleton.slots; for (let i = 0, n = skeleton.slots.length; i < n; i++) { const slot = slots[i]; - if (slot.attachmentState == setupState) { + if (slot.attachmentState === setupState) { const attachmentName = slot.data.attachmentName; slot.pose.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); } @@ -246,23 +248,23 @@ export class AnimationState { } applyMixingFrom (to: TrackEntry, skeleton: Skeleton, blend: MixBlend) { - let from = to.mixingFrom!; + const from = to.mixingFrom!; if (from.mixingFrom) this.applyMixingFrom(from, skeleton, blend); let mix = 0; - if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. + if (to.mixDuration === 0) { // Single frame mix to undo mixingFrom changes. mix = 1; - if (blend == MixBlend.first) blend = MixBlend.setup; + if (blend === MixBlend.first) blend = MixBlend.setup; } else { mix = to.mixTime / to.mixDuration; if (mix > 1) mix = 1; - if (blend != MixBlend.first) blend = from.mixBlend; + if (blend !== MixBlend.first) blend = from.mixBlend; } - let attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; - let timelines = from.animation!.timelines; - let timelineCount = timelines.length; - let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + const attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; + const timelines = from.animation!.timelines; + const timelineCount = timelines.length; + const alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; let events = null; if (from.reverse) @@ -270,20 +272,20 @@ export class AnimationState { else if (mix < from.eventThreshold) events = this.events; - if (blend == MixBlend.add) { + if (blend === MixBlend.add) { for (let i = 0; i < timelineCount; i++) timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.out, false); } else { - let timelineMode = from.timelineMode; - let timelineHoldMix = from.timelineHoldMix; + const timelineMode = from.timelineMode; + const timelineHoldMix = from.timelineHoldMix; - let shortestRotation = from.shortestRotation; - let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1; + const shortestRotation = from.shortestRotation; + const firstFrame = !shortestRotation && from.timelinesRotation.length !== timelineCount << 1; if (firstFrame) from.timelinesRotation.length = timelineCount << 1; from.totalAlpha = 0; for (let i = 0; i < timelineCount; i++) { - let timeline = timelines[i]; + const timeline = timelines[i]; let direction = MixDirection.out; let timelineBlend: MixBlend; let alpha = 0; @@ -305,11 +307,12 @@ export class AnimationState { timelineBlend = MixBlend.setup; alpha = alphaHold; break; - default: // HOLD_MIX + default: { // HOLD_MIX timelineBlend = MixBlend.setup; - let holdMix = timelineHoldMix[i]; + const holdMix = timelineHoldMix[i]; alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); break; + } } from.totalAlpha += alpha; @@ -320,7 +323,7 @@ export class AnimationState { else { // This fixes the WebKit 602 specific issue described at https://esotericsoftware.com/forum/d/10109-ios-10-disappearing-graphics Utils.webkit602BugfixHelper(alpha, blend); - if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == MixBlend.setup) + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend === MixBlend.setup) direction = MixDirection.in; timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction, false); } @@ -340,7 +343,7 @@ export class AnimationState { if (!slot.bone.active) return; if (time < timeline.frames[0]) { // Time is before first frame. - if (blend == MixBlend.setup || blend == MixBlend.first) + if (blend === MixBlend.setup || blend === MixBlend.first) this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); } else this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search(timeline.frames, time)], attachments); @@ -359,20 +362,22 @@ export class AnimationState { if (firstFrame) timelinesRotation[i] = 0; - if (alpha == 1) { + if (alpha === 1) { timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.in, false); return; } - let bone = skeleton.bones[timeline.boneIndex]; + const bone = skeleton.bones[timeline.boneIndex]; if (!bone.active) return; const pose = bone.pose, setup = bone.data.setup; - let frames = timeline.frames; + const frames = timeline.frames; let r1 = 0, r2 = 0; if (time < frames[0]) { switch (blend) { + // biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime does fall through case MixBlend.setup: pose.rotation = setup.rotation; + // biome-ignore lint/suspicious/useDefaultSwitchClauseLast: needed for fall through default: return; case MixBlend.first: @@ -380,14 +385,14 @@ export class AnimationState { r2 = setup.rotation; } } else { - r1 = blend == MixBlend.setup ? setup.rotation : pose.rotation; + r1 = blend === MixBlend.setup ? setup.rotation : pose.rotation; r2 = setup.rotation + timeline.getCurveValue(time); } // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. let total = 0, diff = r2 - r1; diff -= Math.ceil(diff / 360 - 0.5) * 360; - if (diff == 0) { + if (diff === 0) { total = timelinesRotation[i]; } else { let lastTotal = 0, lastDiff = 0; @@ -398,19 +403,19 @@ export class AnimationState { lastTotal = timelinesRotation[i]; lastDiff = timelinesRotation[i + 1]; } - let loops = lastTotal - lastTotal % 360; + const loops = lastTotal - lastTotal % 360; total = diff + loops; let current = diff >= 0, dir = lastTotal >= 0; - if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) { + if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) !== MathUtils.signum(diff)) { if (Math.abs(lastTotal - loops) > 180) { total += 360 * MathUtils.signum(lastTotal); dir = current; - } else if (loops != 0) + } else if (loops !== 0) total -= 360 * MathUtils.signum(lastTotal); else dir = current; } - if (dir != current) total += 360 * MathUtils.signum(lastTotal); + if (dir !== current) total += 360 * MathUtils.signum(lastTotal); timelinesRotation[i] = total; } timelinesRotation[i + 1] = diff; @@ -418,15 +423,15 @@ export class AnimationState { } queueEvents (entry: TrackEntry, animationTime: number) { - let animationStart = entry.animationStart, animationEnd = entry.animationEnd; - let duration = animationEnd - animationStart; - let trackLastWrapped = entry.trackLast % duration; + const animationStart = entry.animationStart, animationEnd = entry.animationEnd; + const duration = animationEnd - animationStart; + const trackLastWrapped = entry.trackLast % duration; // Queue events before complete. - let events = this.events; + const events = this.events; let i = 0, n = events.length; for (; i < n; i++) { - let event = events[i]; + const event = events[i]; if (event.time < trackLastWrapped) break; if (event.time > animationEnd) continue; // Discard events outside animation start/end. this.queue.event(entry, event); @@ -435,7 +440,7 @@ export class AnimationState { // Queue complete if completed a loop iteration or the animation. let complete = false; if (entry.loop) { - if (duration == 0) + if (duration === 0) complete = true; else { const cycles = Math.floor(entry.trackTime / duration); @@ -447,7 +452,7 @@ export class AnimationState { // Queue events after complete. for (; i < n; i++) { - let event = events[i]; + const event = events[i]; if (event.time < animationStart) continue; // Discard events outside animation start/end. this.queue.event(entry, event); } @@ -458,7 +463,7 @@ export class AnimationState { * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, * rather than leaving them in their current pose. */ clearTracks () { - let oldDrainDisabled = this.queue.drainDisabled; + const oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (let i = 0, n = this.tracks.length; i < n; i++) this.clearTrack(i); @@ -473,7 +478,7 @@ export class AnimationState { * rather than leaving them in their current pose. */ clearTrack (trackIndex: number) { if (trackIndex >= this.tracks.length) return; - let current = this.tracks[trackIndex]; + const current = this.tracks[trackIndex]; if (!current) return; this.queue.end(current); @@ -482,7 +487,7 @@ export class AnimationState { let entry = current; while (true) { - let from = entry.mixingFrom; + const from = entry.mixingFrom; if (!from) break; this.queue.end(from); entry.mixingFrom = null; @@ -496,7 +501,7 @@ export class AnimationState { } setCurrent (index: number, current: TrackEntry, interrupt: boolean) { - let from = this.expandToIndex(index); + const from = this.expandToIndex(index); this.tracks[index] = current; current.previous = null; @@ -538,8 +543,8 @@ export class AnimationState { } private setAnimation1 (trackIndex: number, animationName: string, loop: boolean = false) { - let animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw new Error("Animation not found: " + animationName); + const animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error(`Animation not found: ${animationName}`); return this.setAnimation2(trackIndex, animation, loop); } @@ -568,7 +573,7 @@ export class AnimationState { } else this.clearNext(current); } - let entry = this.trackEntry(trackIndex, animation, loop, current); + const entry = this.trackEntry(trackIndex, animation, loop, current); this.setCurrent(trackIndex, entry, interrupt); this.queue.drain(); return entry; @@ -596,8 +601,8 @@ export class AnimationState { } private addAnimation1 (trackIndex: number, animationName: string, loop: boolean = false, delay: number = 0) { - let animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw new Error("Animation not found: " + animationName); + const animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error(`Animation not found: ${animationName}`); return this.addAnimation2(trackIndex, animation, loop, delay); } @@ -610,7 +615,7 @@ export class AnimationState { last = last.next; } - let entry = this.trackEntry(trackIndex, animation, loop, last); + const entry = this.trackEntry(trackIndex, animation, loop, last); if (!last) { this.setCurrent(trackIndex, entry, true); @@ -644,7 +649,7 @@ export class AnimationState { * See Empty animations in the Spine * Runtimes Guide. */ setEmptyAnimation (trackIndex: number, mixDuration: number = 0) { - let entry = this.setAnimation(trackIndex, AnimationState.emptyAnimation, false); + const entry = this.setAnimation(trackIndex, AnimationState.emptyAnimation, false); entry.mixDuration = mixDuration; entry.trackEnd = mixDuration; return entry; @@ -664,7 +669,7 @@ export class AnimationState { * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */ addEmptyAnimation (trackIndex: number, mixDuration: number = 0, delay: number = 0) { - let entry = this.addAnimation(trackIndex, AnimationState.emptyAnimation, false, delay); + const entry = this.addAnimation(trackIndex, AnimationState.emptyAnimation, false, delay); if (delay <= 0) entry.delay = Math.max(entry.delay + entry.mixDuration - mixDuration, 0); entry.mixDuration = mixDuration; entry.trackEnd = mixDuration; @@ -676,10 +681,10 @@ export class AnimationState { * See Empty animations in the Spine * Runtimes Guide. */ setEmptyAnimations (mixDuration: number = 0) { - let oldDrainDisabled = this.queue.drainDisabled; + const oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (let i = 0, n = this.tracks.length; i < n; i++) { - let current = this.tracks[i]; + const current = this.tracks[i]; if (current) this.setEmptyAnimation(current.trackIndex, mixDuration); } this.queue.drainDisabled = oldDrainDisabled; @@ -695,7 +700,7 @@ export class AnimationState { /** @param last May be null. */ trackEntry (trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry | null) { - let entry = this.trackEntryPool.obtain(); + const entry = this.trackEntryPool.obtain(); entry.reset(); entry.trackIndex = trackIndex; entry.animation = animation; @@ -745,30 +750,30 @@ export class AnimationState { this.animationsChanged = false; this.propertyIDs.clear(); - let tracks = this.tracks; + const tracks = this.tracks; for (let i = 0, n = tracks.length; i < n; i++) { let entry = tracks[i]; if (!entry) continue; while (entry.mixingFrom) entry = entry.mixingFrom; do { - if (!entry.mixingTo || entry.mixBlend != MixBlend.add) this.computeHold(entry); + if (!entry.mixingTo || entry.mixBlend !== MixBlend.add) this.computeHold(entry); entry = entry.mixingTo; } while (entry); } } computeHold (entry: TrackEntry) { - let to = entry.mixingTo; - let timelines = entry.animation!.timelines; - let timelinesCount = entry.animation!.timelines.length; - let timelineMode = entry.timelineMode; + const to = entry.mixingTo; + const timelines = entry.animation!.timelines; + const timelinesCount = entry.animation!.timelines.length; + const timelineMode = entry.timelineMode; timelineMode.length = timelinesCount; - let timelineHoldMix = entry.timelineHoldMix; + const timelineHoldMix = entry.timelineHoldMix; timelineHoldMix.length = 0; - let propertyIDs = this.propertyIDs; + const propertyIDs = this.propertyIDs; - if (to && to.holdPrevious) { + if (to?.holdPrevious) { for (let i = 0; i < timelinesCount; i++) timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; return; @@ -776,8 +781,8 @@ export class AnimationState { outer: for (let i = 0; i < timelinesCount; i++) { - let timeline = timelines[i]; - let ids = timeline.getPropertyIds(); + const timeline = timelines[i]; + const ids = timeline.getPropertyIds(); if (!propertyIDs.addAll(ids)) timelineMode[i] = SUBSEQUENT; else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline @@ -812,7 +817,7 @@ export class AnimationState { /** Removes the listener added with {@link #addListener()}. */ removeListener (listener: AnimationStateListener) { - let index = this.listeners.indexOf(listener); + const index = this.listeners.indexOf(listener); if (index >= 0) this.listeners.splice(index, 1); } @@ -1009,9 +1014,9 @@ export class TrackEntry { * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is next * called. */ mixBlend = MixBlend.replace; - timelineMode = new Array(); - timelineHoldMix = new Array(); - timelinesRotation = new Array(); + timelineMode = [] as number[]; + timelineHoldMix = [] as TrackEntry[]; + timelinesRotation = [] as number[]; reset () { this.next = null; @@ -1030,8 +1035,8 @@ export class TrackEntry { * `animationStart` time. */ getAnimationTime () { if (this.loop) { - let duration = this.animationEnd - this.animationStart; - if (duration == 0) return this.animationStart; + const duration = this.animationEnd - this.animationStart; + if (duration === 0) return this.animationStart; return (this.trackTime % duration) + this.animationStart; } return Math.min(this.trackTime + this.animationStart, this.animationEnd); @@ -1061,8 +1066,8 @@ export class TrackEntry { } getTrackComplete () { - let duration = this.animationEnd - this.animationStart; - if (duration != 0) { + const duration = this.animationEnd - this.animationStart; + if (duration !== 0) { if (this.loop) return duration * (1 + ((this.trackTime / duration) | 0)); // Completion of next loop. if (this.trackTime < duration) return duration; // Before duration. } @@ -1073,7 +1078,7 @@ export class TrackEntry { *

* See {@link AnimationState#apply(Skeleton)}. */ wasApplied () { - return this.nextTrackLast != -1; + return this.nextTrackLast !== -1; } /** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next @@ -1084,7 +1089,7 @@ export class TrackEntry { } export class EventQueue { - objects: Array = []; + objects: Array = []; drainDisabled = false; animState: AnimationState; @@ -1137,28 +1142,29 @@ export class EventQueue { const entry = objects[i + 1] as TrackEntry; switch (type) { case EventType.start: - if (entry.listener && entry.listener.start) entry.listener.start(entry); + if (entry.listener?.start) entry.listener.start(entry); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.start) listener.start(entry); } break; case EventType.interrupt: - if (entry.listener && entry.listener.interrupt) entry.listener.interrupt(entry); + if (entry.listener?.interrupt) entry.listener.interrupt(entry); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.interrupt) listener.interrupt(entry); } break; + // biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime does fall through case EventType.end: - if (entry.listener && entry.listener.end) entry.listener.end(entry); + if (entry.listener?.end) entry.listener.end(entry); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.end) listener.end(entry); } // Fall through. case EventType.dispose: - if (entry.listener && entry.listener.dispose) entry.listener.dispose(entry); + if (entry.listener?.dispose) entry.listener.dispose(entry); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.dispose) listener.dispose(entry); @@ -1166,20 +1172,21 @@ export class EventQueue { this.animState.trackEntryPool.free(entry); break; case EventType.complete: - if (entry.listener && entry.listener.complete) entry.listener.complete(entry); + if (entry.listener?.complete) entry.listener.complete(entry); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.complete) listener.complete(entry); } break; - case EventType.event: + case EventType.event: { const event = objects[i++ + 2] as Event; - if (entry.listener && entry.listener.event) entry.listener.event(entry, event); + if (entry.listener?.event) entry.listener.event(entry, event); for (let ii = 0; ii < listeners.length; ii++) { const listener = listeners[ii]; if (listener.event) listener.event(entry, event); } break; + } } } this.clear(); diff --git a/spine-ts/spine-core/src/AnimationStateData.ts b/spine-ts/spine-core/src/AnimationStateData.ts index 725b34a8c..e98df1e35 100644 --- a/spine-ts/spine-core/src/AnimationStateData.ts +++ b/spine-ts/spine-core/src/AnimationStateData.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation } from "./Animation.js"; -import { SkeletonData } from "./SkeletonData.js"; -import { StringMap } from "./Utils.js"; +import type { Animation } from "./Animation.js"; +import type { SkeletonData } from "./SkeletonData.js"; +import type { StringMap } from "./Utils.js"; /** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */ @@ -50,12 +50,12 @@ export class AnimationStateData { /** Sets a mix duration by animation name. * * See {@link #setMix()}. */ - setMix (fromName: string, to: string, duration: number): any; + setMix (fromName: string, to: string, duration: number): void; /** Sets the mix duration when changing from the specified animation to the other. * * See {@link TrackEntry#mixDuration}. */ - setMix (from: Animation, to: Animation, duration: number): any; + setMix (from: Animation, to: Animation, duration: number): void; setMix (from: string | Animation, to: string | Animation, duration: number) { if (typeof from === "string") @@ -64,25 +64,25 @@ export class AnimationStateData { } private setMix1 (fromName: string, toName: string, duration: number) { - let from = this.skeletonData.findAnimation(fromName); - if (!from) throw new Error("Animation not found: " + fromName); - let to = this.skeletonData.findAnimation(toName); - if (!to) throw new Error("Animation not found: " + toName); + const from = this.skeletonData.findAnimation(fromName); + if (!from) throw new Error(`Animation not found: ${fromName}`); + const to = this.skeletonData.findAnimation(toName); + if (!to) throw new Error(`Animation not found: ${toName}`); this.setMix2(from, to, duration); } private setMix2 (from: Animation, to: Animation, duration: number) { if (!from) throw new Error("from cannot be null."); if (!to) throw new Error("to cannot be null."); - let key = from.name + "." + to.name; + const key = `${from.name}.${to.name}`; this.animationToMixTime[key] = duration; } /** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if * no mix duration has been set. */ getMix (from: Animation, to: Animation) { - let key = from.name + "." + to.name; - let value = this.animationToMixTime[key]; + const key = `${from.name}.${to.name}`; + const value = this.animationToMixTime[key]; return value === undefined ? this.defaultMix : value; } } diff --git a/spine-ts/spine-core/src/AssetManagerBase.ts b/spine-ts/spine-core/src/AssetManagerBase.ts index 52ec70562..ad95c0316 100644 --- a/spine-ts/spine-core/src/AssetManagerBase.ts +++ b/spine-ts/spine-core/src/AssetManagerBase.ts @@ -27,9 +27,13 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Texture } from "./Texture.js"; +import type { Texture } from "./Texture.js"; import { TextureAtlas } from "./TextureAtlas.js"; -import { Disposable, StringMap } from "./Utils.js"; +import type { Disposable, StringMap } from "./Utils.js"; + +type AssetData = (Uint8Array | string | Texture | TextureAtlas | object) & Partial; +type AssetCallback = (path: string, data: T) => void; +type ErrorCallback = (path: string, message: string) => void; export class AssetManagerBase implements Disposable { private pathPrefix: string = ""; @@ -52,7 +56,7 @@ export class AssetManagerBase implements Disposable { return this.pathPrefix + path; } - private success (callback: (path: string, data: any) => void, path: string, asset: any) { + private success (callback: AssetCallback, path: string, asset: T) { this.toLoad--; this.loaded++; this.cache.assets[path] = asset; @@ -68,8 +72,8 @@ export class AssetManagerBase implements Disposable { } loadAll () { - let promise = new Promise((resolve: (assetManager: AssetManagerBase) => void, reject: (errors: StringMap) => void) => { - let check = () => { + const promise = new Promise((resolve: (assetManager: AssetManagerBase) => void, reject: (errors: StringMap) => void) => { + const check = () => { if (this.isLoadingComplete()) { if (this.hasErrors()) reject(this.errors); else resolve(this); @@ -93,7 +97,7 @@ export class AssetManagerBase implements Disposable { if (this.reuseAssets(path, success, error)) return; - this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadBinary(path, (data: Uint8Array): void => { this.success(success, path, data); resolve(data); @@ -124,7 +128,7 @@ export class AssetManagerBase implements Disposable { if (this.reuseAssets(path, success, error)) return; - this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadJson(path, (data: object): void => { this.success(success, path, data); resolve(data); @@ -136,36 +140,44 @@ export class AssetManagerBase implements Disposable { }); } - reuseAssets (path: string, - success: (path: string, data: any) => void = () => { }, - error: (path: string, message: string) => void = () => { }) { - const loadedStatus = this.cache.assetsLoaded[path]; + + reuseAssets ( + path: string, + success: AssetCallback = () => { }, + error: ErrorCallback = () => { } + ) { + const loadedStatus = this.cache.getAsset(path); const alreadyExistsOrLoading = loadedStatus !== undefined; if (alreadyExistsOrLoading) { this.cache.assetsLoaded[path] = loadedStatus .then(data => { // necessary when user preloads an image into the cache. // texture loader is not avaiable in the cache, so we transform in GLTexture at first use - data = (data instanceof Image || data instanceof ImageBitmap) ? this.textureLoader(data) : data; - this.success(success, path, data); + data = (data instanceof Image || data instanceof ImageBitmap) ? this.textureLoader(data) as T : data; + this.success(success, path, data as T); return data; }) - .catch(errorMsg => this.error(error, path, errorMsg)); + .catch(errorMsg => { + this.error(error, path, errorMsg); + return undefined; + }); } return alreadyExistsOrLoading; } - loadTexture (path: string, - success: (path: string, texture: Texture) => void = () => { }, - error: (path: string, message: string) => void = () => { }) { + loadTexture ( + path: string, + success: AssetCallback = () => { }, + error: ErrorCallback = () => { } + ) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; - this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { - let isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document); - let isWebWorker = !isBrowser; // && typeof importScripts !== 'undefined'; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + const isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document); + const isWebWorker = !isBrowser; // && typeof importScripts !== 'undefined'; if (isWebWorker) { fetch(path, { mode: "cors" }).then((response) => { if (response.ok) return response.blob(); @@ -182,7 +194,7 @@ export class AssetManagerBase implements Disposable { }; }); } else { - let image = new Image(); + const image = new Image(); image.crossOrigin = "anonymous"; image.onload = () => { const texture = this.createTexture(path, image); @@ -200,28 +212,29 @@ export class AssetManagerBase implements Disposable { }); } - loadTextureAtlas (path: string, - success: (path: string, atlas: TextureAtlas) => void = () => { }, - error: (path: string, message: string) => void = () => { }, + loadTextureAtlas ( + path: string, + success: AssetCallback = () => { }, + error: ErrorCallback = () => { }, fileAlias?: { [keyword: string]: string } ) { - let index = path.lastIndexOf("/"); - let parent = index >= 0 ? path.substring(0, index + 1) : ""; + const index = path.lastIndexOf("/"); + const parent = index >= 0 ? path.substring(0, index + 1) : ""; path = this.start(path); if (this.reuseAssets(path, success, error)) return; - this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadText(path, (atlasText: string): void => { try { const atlas = this.createTextureAtlas(path, atlasText); let toLoad = atlas.pages.length, abort = false; - for (let page of atlas.pages) { - this.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name!], + for (const page of atlas.pages) { + this.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name], (imagePath: string, texture: Texture) => { if (!abort) { page.setTexture(texture); - if (--toLoad == 0) { + if (--toLoad === 0) { this.success(success, path, atlas); resolve(atlas); } @@ -237,8 +250,8 @@ export class AssetManagerBase implements Disposable { } ); } - } catch (e) { - const errorMsg = `Couldn't parse texture atlas ${path}: ${(e as any).message}`; + } catch (e: unknown) { + const errorMsg = `Couldn't parse texture atlas ${path}: ${(e as Error).message}`; this.error(error, path, errorMsg); reject(errorMsg); } @@ -250,23 +263,23 @@ export class AssetManagerBase implements Disposable { }); } - loadTextureAtlasButNoTextures (path: string, - success: (path: string, atlas: TextureAtlas) => void = () => { }, - error: (path: string, message: string) => void = () => { }, - fileAlias?: { [keyword: string]: string } + loadTextureAtlasButNoTextures ( + path: string, + success: AssetCallback = () => { }, + error: ErrorCallback = () => { }, ) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; - this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadText(path, (atlasText: string): void => { try { const atlas = this.createTextureAtlas(path, atlasText); this.success(success, path, atlas); resolve(atlas); } catch (e) { - const errorMsg = `Couldn't parse texture atlas ${path}: ${(e as any).message}`; + const errorMsg = `Couldn't parse texture atlas ${path}: ${(e as Error).message}`; this.error(error, path, errorMsg); reject(errorMsg); } @@ -334,15 +347,15 @@ export class AssetManagerBase implements Disposable { require (path: string) { path = this.pathPrefix + path; - let asset = this.cache.assets[path]; + const asset = this.cache.assets[path]; if (asset) return asset; - let error = this.errors[path]; - throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + const error = this.errors[path]; + throw Error(`Asset not found: ${path}${error ? `\n${error}` : ""}`); } remove (path: string) { path = this.pathPrefix + path; - let asset = this.cache.assets[path]; + const asset = this.cache.assets[path]; if (asset.dispose) asset.dispose(); delete this.cache.assets[path]; delete this.cache.assetsRefCount[path]; @@ -351,8 +364,8 @@ export class AssetManagerBase implements Disposable { } removeAll () { - for (let path in this.cache.assets) { - let asset = this.cache.assets[path]; + for (const path in this.cache.assets) { + const asset = this.cache.assets[path]; if (asset.dispose) asset.dispose(); } this.cache.assets = {}; @@ -361,7 +374,7 @@ export class AssetManagerBase implements Disposable { } isLoadingComplete (): boolean { - return this.toLoad == 0; + return this.toLoad === 0; } getToLoad (): number { @@ -423,9 +436,9 @@ export class AssetManagerBase implements Disposable { } export class AssetCache { - public assets: StringMap = {}; + public assets: StringMap = {}; public assetsRefCount: StringMap = {}; - public assetsLoaded: StringMap> = {}; + public assetsLoaded: StringMap> = {}; static AVAILABLE_CACHES = new Map(); static getCache (id: string) { @@ -437,14 +450,22 @@ export class AssetCache { return newCache; } - async addAsset (path: string, asset: any) { + async addAsset (path: string, asset: T): Promise { this.assetsLoaded[path] = Promise.resolve(asset); - this.assets[path] = await asset; + this.assets[path] = asset; + return asset; + } + + getAsset (path: string): Promise | undefined { + return this.assetsLoaded[path] as Promise | undefined; } } +type DownloaderSuccessCallback = (data: T) => void; +type DownloaderErrorCallback = (status: number, responseText: string) => void; + export class Downloader { - private callbacks: StringMap> = {}; + private callbacks: StringMap> = {}; rawDataUris: StringMap = {}; dataUriToString (dataUri: string) { @@ -453,7 +474,7 @@ export class Downloader { } let base64Idx = dataUri.indexOf("base64,"); - if (base64Idx != -1) { + if (base64Idx !== -1) { base64Idx += "base64,".length; return atob(dataUri.substr(base64Idx)); } else { @@ -465,7 +486,7 @@ export class Downloader { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); - for (var i = 0; i < len; i++) { + for (let i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes; @@ -477,12 +498,12 @@ export class Downloader { } let base64Idx = dataUri.indexOf("base64,"); - if (base64Idx == -1) throw new Error("Not a binary data URI."); + if (base64Idx === -1) throw new Error("Not a binary data URI."); base64Idx += "base64,".length; return this.base64ToUint8Array(dataUri.substr(base64Idx)); } - downloadText (url: string, success: (data: string) => void, error: (status: number, responseText: string) => void) { + downloadText (url: string, success: DownloaderSuccessCallback, error: DownloaderErrorCallback) { if (this.start(url, success, error)) return; const rawDataUri = this.rawDataUris[url]; @@ -496,10 +517,10 @@ export class Downloader { return; } - let request = new XMLHttpRequest(); + const request = new XMLHttpRequest(); request.overrideMimeType("text/html"); request.open("GET", rawDataUri ? rawDataUri : url, true); - let done = () => { + const done = () => { this.finish(url, request.status, request.responseText); }; request.onload = done; @@ -507,13 +528,13 @@ export class Downloader { request.send(); } - downloadJson (url: string, success: (data: object) => void, error: (status: number, responseText: string) => void) { + downloadJson (url: string, success: DownloaderSuccessCallback, error: DownloaderErrorCallback) { this.downloadText(url, (data: string): void => { success(JSON.parse(data)); }, error); } - downloadBinary (url: string, success: (data: Uint8Array) => void, error: (status: number, responseText: string) => void) { + downloadBinary (url: string, success: (data: Uint8Array) => void, error: DownloaderErrorCallback) { if (this.start(url, success, error)) return; const rawDataUri = this.rawDataUris[url]; @@ -527,14 +548,14 @@ export class Downloader { return; } - let request = new XMLHttpRequest(); + const request = new XMLHttpRequest(); request.open("GET", rawDataUri ? rawDataUri : url, true); request.responseType = "arraybuffer"; - let onerror = () => { + const onerror = () => { this.finish(url, request.status, request.response); }; request.onload = () => { - if (request.status == 200 || request.status == 0) + if (request.status === 200 || request.status === 0) this.finish(url, 200, new Uint8Array(request.response as ArrayBuffer)); else onerror(); @@ -543,21 +564,25 @@ export class Downloader { request.send(); } - private start (url: string, success: any, error: any) { + private start (url: string, success: DownloaderSuccessCallback, error: DownloaderErrorCallback) { let callbacks = this.callbacks[url]; try { if (callbacks) return true; this.callbacks[url] = callbacks = []; } finally { - callbacks.push(success, error); + callbacks.push(success as DownloaderSuccessCallback, error); } } - private finish (url: string, status: number, data: any) { - let callbacks = this.callbacks[url]; + private finish (url: string, status: number, data: AssetData) { + const callbacks = this.callbacks[url]; delete this.callbacks[url]; - let args = status == 200 || status == 0 ? [data] : [status, data]; - for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) - callbacks[i].apply(null, args); + if (status === 200 || status === 0) { + for (let i = 0, n = callbacks.length; i < n; i += 2) + (callbacks[i] as DownloaderSuccessCallback)(data); + } else { + for (let i = 1, n = callbacks.length; i < n; i += 2) + (callbacks[i] as DownloaderErrorCallback)(status, data as string); + } } } diff --git a/spine-ts/spine-core/src/Bone.ts b/spine-ts/spine-core/src/Bone.ts index 2113b29f1..e85203fb7 100644 --- a/spine-ts/spine-core/src/Bone.ts +++ b/spine-ts/spine-core/src/Bone.ts @@ -27,8 +27,8 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { BoneData } from "./BoneData.js"; -import { BoneLocal } from "./BoneLocal.js"; +import type { BoneData } from "./BoneData.js"; +import type { BoneLocal } from "./BoneLocal.js"; import { BonePose } from "./BonePose.js"; import { PosedActive } from "./PosedActive.js"; @@ -42,7 +42,7 @@ export class Bone extends PosedActive { parent: Bone | null = null; /** The immediate children of this bone. */ - children = new Array(); + children = [] as Bone[]; sorted = false; diff --git a/spine-ts/spine-core/src/BoneData.ts b/spine-ts/spine-core/src/BoneData.ts index 157654b7a..1b0697a29 100644 --- a/spine-ts/spine-core/src/BoneData.ts +++ b/spine-ts/spine-core/src/BoneData.ts @@ -29,9 +29,8 @@ import { BoneLocal } from "./BoneLocal.js"; import { PosedData } from "./PosedData.js"; -import { Color } from "./Utils.js"; - import type { Skeleton } from "./Skeleton.js"; +import { Color } from "./Utils.js"; /** The setup pose for a bone. */ export class BoneData extends PosedData { diff --git a/spine-ts/spine-core/src/BoneLocal.ts b/spine-ts/spine-core/src/BoneLocal.ts index dc68e8095..28b68f153 100644 --- a/spine-ts/spine-core/src/BoneLocal.ts +++ b/spine-ts/spine-core/src/BoneLocal.ts @@ -28,7 +28,7 @@ *****************************************************************************/ import { Inherit } from "./BoneData.js"; -import { Pose } from "./Pose.js" +import type { Pose } from "./Pose.js" /** Stores a bone's local pose. */ export class BoneLocal implements Pose { diff --git a/spine-ts/spine-core/src/BonePose.ts b/spine-ts/spine-core/src/BonePose.ts index 8788200f3..06aaa3ad0 100644 --- a/spine-ts/spine-core/src/BonePose.ts +++ b/spine-ts/spine-core/src/BonePose.ts @@ -27,13 +27,13 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Bone } from "./Bone.js"; +import type { Bone } from "./Bone.js"; import { Inherit } from "./BoneData.js"; import { BoneLocal } from "./BoneLocal.js"; -import { Physics } from "./Physics.js"; -import { Skeleton } from "./Skeleton.js"; -import { Update } from "./Update.js"; -import { MathUtils, Vector2 } from "./Utils.js"; +import type { Physics } from "./Physics.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Update } from "./Update.js"; +import { MathUtils, type Vector2 } from "./Utils.js"; /** The applied pose for a bone. This is the {@link Bone} pose with constraints applied and the world transform computed by * {@link Skeleton#updateWorldTransform()}. */ @@ -76,7 +76,7 @@ export class BonePose extends BoneLocal implements Update { else this.world = skeleton._update; - let rotation = this.rotation; + const rotation = this.rotation; const scaleX = this.scaleX; const scaleY = this.scaleY; const shearX = this.shearX; @@ -123,7 +123,7 @@ export class BonePose extends BoneLocal implements Update { break; } case Inherit.NoRotationOrReflection: { - let sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY; + const sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY; pa *= sx; pc *= sy; let s = pa * pa + pc * pc; @@ -160,7 +160,7 @@ export class BonePose extends BoneLocal implements Update { za *= s; zc *= s; s = Math.sqrt(za * za + zc * zc); - if (this.inherit == Inherit.NoScale && (pa * pd - pb * pc < 0) != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + if (this.inherit === Inherit.NoScale && (pa * pd - pb * pc < 0) !== (skeleton.scaleX < 0 !== skeleton.scaleY < 0)) s = -s; r = Math.PI / 2 + Math.atan2(zc, za); const zb = Math.cos(r) * s; const zd = Math.sin(r) * s; @@ -198,7 +198,7 @@ export class BonePose extends BoneLocal implements Update { if (!this.bone.parent) { this.x = this.worldX - skeleton.x; this.y = this.worldY - skeleton.y; - let a = this.a, b = this.b, c = this.c, d = this.d; + const a = this.a, b = this.b, c = this.c, d = this.d; this.rotation = MathUtils.atan2Deg(c, a); this.scaleX = Math.sqrt(a * a + c * c); this.scaleY = Math.sqrt(b * b + d * d); @@ -211,12 +211,12 @@ export class BonePose extends BoneLocal implements Update { let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; let pid = 1 / (pa * pd - pb * pc); let ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; - let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + const dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; this.x = (dx * ia - dy * ib); this.y = (dy * id - dx * ic); - let ra, rb, rc, rd; - if (this.inherit == Inherit.OnlyTranslation) { + let ra: number, rb: number, rc: number, rd: number; + if (this.inherit === Inherit.OnlyTranslation) { ra = this.a; rb = this.b; rc = this.c; @@ -224,7 +224,7 @@ export class BonePose extends BoneLocal implements Update { } else { switch (this.inherit) { case Inherit.NoRotationOrReflection: { - let s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + const s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); pb = -pc * skeleton.scaleX * s / skeleton.scaleY; pd = pa * skeleton.scaleY * s / skeleton.scaleX; pid = 1 / (pa * pd - pb * pc); @@ -233,7 +233,7 @@ export class BonePose extends BoneLocal implements Update { break; } case Inherit.NoScale: - case Inherit.NoScaleOrReflection: + case Inherit.NoScaleOrReflection: { let r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); pa = (pa * cos + pb * sin) / skeleton.scaleX; pc = (pc * cos + pd * sin) / skeleton.scaleY; @@ -242,7 +242,7 @@ export class BonePose extends BoneLocal implements Update { pa *= s; pc *= s; s = Math.sqrt(pa * pa + pc * pc); - if (this.inherit == Inherit.NoScale && pid < 0 != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + if (this.inherit === Inherit.NoScale && pid < 0 !== (skeleton.scaleX < 0 !== skeleton.scaleY < 0)) s = -s; r = MathUtils.PI / 2 + Math.atan2(pc, pa); pb = Math.cos(r) * s; pd = Math.sin(r) * s; @@ -251,6 +251,7 @@ export class BonePose extends BoneLocal implements Update { ib = pb * pid; ic = pc * pid; id = pa * pid; + } } ra = ia * this.a - ib * this.c; rb = ia * this.b - ib * this.d; @@ -261,7 +262,7 @@ export class BonePose extends BoneLocal implements Update { this.shearX = 0; this.scaleX = Math.sqrt(ra * ra + rc * rc); if (this.scaleX > 0.0001) { - let det = ra * rd - rb * rc; + const det = ra * rd - rb * rc; this.scaleY = det / this.scaleX; this.shearY = -MathUtils.atan2Deg(ra * rb + rc * rd, det); this.rotation = MathUtils.atan2Deg(rc, ra); @@ -341,8 +342,8 @@ export class BonePose extends BoneLocal implements Update { /** Transforms a point from world coordinates to the bone's local coordinates. */ public worldToLocal (world: Vector2): Vector2 { if (world == null) throw new Error("world cannot be null."); - let det = this.a * this.d - this.b * this.c; - let x = world.x - this.worldX, y = world.y - this.worldY; + const det = this.a * this.d - this.b * this.c; + const x = world.x - this.worldX, y = world.y - this.worldY; world.x = (x * this.d - y * this.b) / det; world.y = (y * this.a - x * this.c) / det; return world; @@ -351,7 +352,7 @@ export class BonePose extends BoneLocal implements Update { /** Transforms a point from the bone's local coordinates to world coordinates. */ public localToWorld (local: Vector2): Vector2 { if (local == null) throw new Error("local cannot be null."); - let x = local.x, y = local.y; + const x = local.x, y = local.y; local.x = x * this.a + y * this.b + this.worldX; local.y = x * this.c + y * this.d + this.worldY; return local; @@ -372,14 +373,14 @@ export class BonePose extends BoneLocal implements Update { /** Transforms a world rotation to a local rotation. */ public worldToLocalRotation (worldRotation: number): number { worldRotation *= MathUtils.degRad; - let sin = Math.sin(worldRotation), cos = Math.cos(worldRotation); + const sin = Math.sin(worldRotation), cos = Math.cos(worldRotation); return MathUtils.atan2Deg(this.a * sin - this.c * cos, this.d * cos - this.b * sin) + this.rotation - this.shearX; } /** Transforms a local rotation to a world rotation. */ localToWorldRotation (localRotation: number): number { localRotation = (localRotation - this.rotation - this.shearX) * MathUtils.degRad; - let sin = Math.sin(localRotation), cos = Math.cos(localRotation); + const sin = Math.sin(localRotation), cos = Math.cos(localRotation); return MathUtils.atan2Deg(cos * this.c + sin * this.d, cos * this.a + sin * this.b); } diff --git a/spine-ts/spine-core/src/Constraint.ts b/spine-ts/spine-core/src/Constraint.ts index 921d93726..fd0581bad 100644 --- a/spine-ts/spine-core/src/Constraint.ts +++ b/spine-ts/spine-core/src/Constraint.ts @@ -27,17 +27,17 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { ConstraintData } from "./ConstraintData.js"; -import { Physics } from "./Physics.js"; -import { Pose } from "./Pose.js"; +import type { ConstraintData } from "./ConstraintData.js"; +import type { Physics } from "./Physics.js"; +import type { Pose } from "./Pose.js"; import { PosedActive } from "./PosedActive.js"; -import { Skeleton } from "./Skeleton.js"; -import { Update } from "./Update.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Update } from "./Update.js"; export abstract class Constraint< T extends Constraint, D extends ConstraintData, - P extends Pose> + P extends Pose

> extends PosedActive implements Update { constructor (data: D, pose: P, constrained: P) { diff --git a/spine-ts/spine-core/src/ConstraintData.ts b/spine-ts/spine-core/src/ConstraintData.ts index 70830f412..7a72778ee 100644 --- a/spine-ts/spine-core/src/ConstraintData.ts +++ b/spine-ts/spine-core/src/ConstraintData.ts @@ -27,15 +27,15 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Constraint } from "./Constraint.js"; -import { Pose } from "./Pose.js"; +import type { Constraint } from "./Constraint.js"; +import type { Pose } from "./Pose.js"; import { PosedData } from "./PosedData.js"; -import { Skeleton } from "./Skeleton.js"; +import type { Skeleton } from "./Skeleton.js"; /** The base class for all constraint datas. */ export abstract class ConstraintData< - T extends Constraint, - P extends Pose> + T extends Constraint, P>, + P extends Pose

> extends PosedData

{ constructor (name: string, setup: P) { diff --git a/spine-ts/spine-core/src/Event.ts b/spine-ts/spine-core/src/Event.ts index 67327d231..c1e9e8183 100644 --- a/spine-ts/spine-core/src/Event.ts +++ b/spine-ts/spine-core/src/Event.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { EventData } from "./EventData.js"; +import type { EventData } from "./EventData.js"; import type { Timeline } from "./Animation.js"; import type { AnimationStateListener } from "./AnimationState.js"; diff --git a/spine-ts/spine-core/src/IkConstraint.ts b/spine-ts/spine-core/src/IkConstraint.ts index f9dbed712..c04707c3d 100644 --- a/spine-ts/spine-core/src/IkConstraint.ts +++ b/spine-ts/spine-core/src/IkConstraint.ts @@ -27,14 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Bone } from "./Bone.js"; +import type { Bone } from "./Bone.js"; import { Inherit } from "./BoneData.js"; -import { BonePose } from "./BonePose.js"; +import type { BonePose } from "./BonePose.js"; import { Constraint } from "./Constraint.js"; -import { IkConstraintData } from "./IkConstraintData.js"; +import type { IkConstraintData } from "./IkConstraintData.js"; import { IkConstraintPose } from "./IkConstraintPose.js"; -import { Physics } from "./Physics.js"; -import { Skeleton } from "./Skeleton.js"; +import type { Physics } from "./Physics.js"; +import type { Skeleton } from "./Skeleton.js"; import { MathUtils } from "./Utils.js"; /** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of @@ -52,7 +52,7 @@ export class IkConstraint extends Constraint(); + this.bones = [] as BonePose[]; for (const boneData of data.bones) this.bones.push(skeleton.bones[boneData.index].constrained); @@ -107,16 +107,17 @@ export class IkConstraint extends Constraint 0) { let p = Math.min(1, sd / (softness * 2)) - 1; p = (sd - softness * (1 - p * p)) / td; @@ -235,6 +240,7 @@ export class IkConstraint extends Constraint= 0) { let q = Math.sqrt(d); if (c1 < 0) q = -q; q = -(c1 + q) * 0.5; let r0 = q / c2, r1 = c / q; - let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + const r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; r0 = dd - r * r; if (r0 >= 0) { y = Math.sqrt(r0) * bendDir; @@ -305,7 +311,7 @@ export class IkConstraint extends Constraint 180) a1 -= 360; diff --git a/spine-ts/spine-core/src/IkConstraintData.ts b/spine-ts/spine-core/src/IkConstraintData.ts index af55ed365..9f64c5f1e 100644 --- a/spine-ts/spine-core/src/IkConstraintData.ts +++ b/spine-ts/spine-core/src/IkConstraintData.ts @@ -27,18 +27,18 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { BoneData } from "./BoneData.js"; +import type { BoneData } from "./BoneData.js"; import { ConstraintData } from "./ConstraintData.js"; import { IkConstraint } from "./IkConstraint.js"; import { IkConstraintPose } from "./IkConstraintPose.js"; -import { Skeleton } from "./Skeleton.js"; +import type { Skeleton } from "./Skeleton.js"; /** Stores the setup pose for an {@link IkConstraint}. * * See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */ export class IkConstraintData extends ConstraintData { /** The bones that are constrained by this IK constraint. */ - bones = new Array(); + bones = [] as BoneData[]; private _target: BoneData | null = null; /** The bone that is the IK target. */ diff --git a/spine-ts/spine-core/src/IkConstraintPose.ts b/spine-ts/spine-core/src/IkConstraintPose.ts index 60f7e24b1..f827470ad 100644 --- a/spine-ts/spine-core/src/IkConstraintPose.ts +++ b/spine-ts/spine-core/src/IkConstraintPose.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose"; +import type { Pose } from "./Pose"; /** Stores the current pose for an IK constraint. */ export class IkConstraintPose implements Pose { diff --git a/spine-ts/spine-core/src/PathConstraint.ts b/spine-ts/spine-core/src/PathConstraint.ts index 2572b10b5..535e90baa 100644 --- a/spine-ts/spine-core/src/PathConstraint.ts +++ b/spine-ts/spine-core/src/PathConstraint.ts @@ -27,18 +27,18 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Attachment } from "./attachments/Attachment.js"; +import type { Attachment } from "./attachments/Attachment.js"; import { PathAttachment } from "./attachments/PathAttachment.js"; -import { Bone } from "./Bone.js"; -import { BonePose } from "./BonePose.js"; +import type { Bone } from "./Bone.js"; +import type { BonePose } from "./BonePose.js"; import { Constraint } from "./Constraint.js"; -import { PathConstraintData, RotateMode, SpacingMode, PositionMode } from "./PathConstraintData.js"; +import { type PathConstraintData, PositionMode, RotateMode, SpacingMode } from "./PathConstraintData.js"; import { PathConstraintPose } from "./PathConstraintPose.js"; -import { Physics } from "./Physics.js"; -import { Skeleton } from "./Skeleton.js"; -import { Skin, SkinEntry } from "./Skin.js"; -import { Slot } from "./Slot.js"; -import { Utils, MathUtils } from "./Utils.js"; +import type { Physics } from "./Physics.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Skin } from "./Skin.js"; +import type { Slot } from "./Slot.js"; +import { MathUtils, Utils } from "./Utils.js"; /** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the @@ -58,16 +58,16 @@ export class PathConstraint extends Constraint(); positions = new Array(); - world = new Array(); curves = new Array(); lengths = new Array(); - segments = new Array(); + spaces = [] as number[]; positions = [] as number[]; + world = [] as number[]; curves = [] as number[]; lengths = [] as number[]; + segments = [] as number[]; constructor (data: PathConstraintData, skeleton: Skeleton) { super(data, new PathConstraintPose(), new PathConstraintPose()); if (!skeleton) throw new Error("skeleton cannot be null."); this.data = data; - this.bones = new Array(); + this.bones = [] as BonePose[]; for (const boneData of this.data.bones) this.bones.push(skeleton.bones[boneData.index].constrained); @@ -81,44 +81,44 @@ export class PathConstraint extends Constraint = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; - let spacing = p.spacing; + const bones = this.bones; + const boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + const spaces = Utils.setArraySize(this.spaces, spacesCount), lengths: Array = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + const spacing = p.spacing; switch (data.spacingMode) { case SpacingMode.Percent: if (scale) { for (let i = 0, n = spacesCount - 1; i < n; i++) { - let bone = bones[i]; - let setupLength = bone.bone.data.length; - let x = setupLength * bone.a, y = setupLength * bone.c; + const bone = bones[i]; + const setupLength = bone.bone.data.length; + const x = setupLength * bone.a, y = setupLength * bone.c; lengths[i] = Math.sqrt(x * x + y * y); } } Utils.arrayFill(spaces, 1, spacesCount, spacing); break; - case SpacingMode.Proportional: + case SpacingMode.Proportional: { let sum = 0; for (let i = 0, n = spacesCount - 1; i < n;) { - let bone = bones[i]; - let setupLength = bone.bone.data.length; + const bone = bones[i]; + const setupLength = bone.bone.data.length; if (setupLength < PathConstraint.epsilon) { if (scale) lengths[i] = 0; spaces[++i] = spacing; } else { - let x = setupLength * bone.a, y = setupLength * bone.c; - let length = Math.sqrt(x * x + y * y); + const x = setupLength * bone.a, y = setupLength * bone.c; + const length = Math.sqrt(x * x + y * y); if (scale) lengths[i] = length; spaces[++i] = length; sum += length; @@ -130,42 +130,44 @@ export class PathConstraint extends Constraint 0 ? MathUtils.degRad : -MathUtils.degRad; } for (let i = 0, ip = 3, u = skeleton._update; i < boneCount; i++, ip += 3) { - let bone = bones[i]; + const bone = bones[i]; bone.worldX += (boneX - bone.worldX) * mixX; bone.worldY += (boneY - bone.worldY) * mixY; - let x = positions[ip], y = positions[ip + 1], dx = x - boneX, dy = y - boneY; + const x = positions[ip], y = positions[ip + 1], dx = x - boneX, dy = y - boneY; if (scale) { - let length = lengths[i]; - if (length != 0) { - let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + const length = lengths[i]; + if (length !== 0) { + const s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; bone.a *= s; bone.c *= s; } @@ -176,7 +178,7 @@ export class PathConstraint extends Constraint = this.world; - let closed = path.closed; + const closed = path.closed; let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; if (!path.constantSpeed) { - let lengths = path.lengths; + const lengths = path.lengths; curveCount -= closed ? 1 : 2; - let pathLength = lengths[curveCount]; - if (this.data.positionMode == PositionMode.Percent) position *= pathLength; + const pathLength = lengths[curveCount]; + if (this.data.positionMode === PositionMode.Percent) position *= pathLength; - let multiplier; + let multiplier: number; switch (this.data.spacingMode) { case SpacingMode.Percent: multiplier = pathLength; break; case SpacingMode.Proportional: multiplier = pathLength / spacesCount; break; @@ -228,7 +230,7 @@ export class PathConstraint extends Constraint pathLength) { - if (prevCurve != PathConstraint.AFTER) { + if (prevCurve !== PathConstraint.AFTER) { prevCurve = PathConstraint.AFTER; path.computeWorldVertices(skeleton, slot, verticesLength - 6, 4, world, 0, 2); } @@ -254,26 +256,26 @@ export class PathConstraint extends Constraint length) continue; - if (curve == 0) + if (curve === 0) p /= length; else { - let prev = lengths[curve - 1]; + const prev = lengths[curve - 1]; p = (p - prev) / (length - prev); } break; } - if (curve != prevCurve) { + if (curve !== prevCurve) { prevCurve = curve; - if (closed && curve == curveCount) { + if (closed && curve === curveCount) { path.computeWorldVertices(skeleton, slot, verticesLength - 4, 4, world, 0, 2); path.computeWorldVertices(skeleton, slot, 0, 4, world, 4, 2); } else path.computeWorldVertices(skeleton, slot, curve * 6 + 2, 8, world, 0, 2); } this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, - tangents || (i > 0 && space == 0)); + tangents || (i > 0 && space === 0)); } return out; } @@ -294,7 +296,7 @@ export class PathConstraint extends Constraint length) continue; - if (curve == 0) + if (curve === 0) p /= length; else { - let prev = curves[curve - 1]; + const prev = curves[curve - 1]; p = (p - prev) / (length - prev); } break; } // Curve segment lengths. - if (curve != prevCurve) { + if (curve !== prevCurve) { prevCurve = curve; let ii = curve * 6; x1 = world[ii]; @@ -416,30 +418,30 @@ export class PathConstraint extends Constraint length) continue; - if (segment == 0) + if (segment === 0) p /= length; else { - let prev = segments[segment - 1]; + const prev = segments[segment - 1]; p = segment + (p - prev) / (length - prev); } break; } - this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space === 0)); } return out; } addBeforePosition (p: number, temp: Array, i: number, out: Array, o: number) { - let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + const x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); out[o] = x1 + p * Math.cos(r); out[o + 1] = y1 + p * Math.sin(r); out[o + 2] = r; } addAfterPosition (p: number, temp: Array, i: number, out: Array, o: number) { - let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + const x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); out[o] = x1 + p * Math.cos(r); out[o + 1] = y1 + p * Math.sin(r); out[o + 2] = r; @@ -447,15 +449,15 @@ export class PathConstraint extends Constraint, o: number, tangents: boolean) { - if (p == 0 || isNaN(p)) { + if (p === 0 || Number.isNaN(p)) { out[o] = x1; out[o + 1] = y1; out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); return; } - let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; - let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; - let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + const tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + const ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + const x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; out[o] = x; out[o + 1] = y; if (tangents) { @@ -470,7 +472,7 @@ export class PathConstraint extends Constraint { /** The bones that will be modified by this path constraint. */ - bones = new Array(); + bones = [] as BoneData[]; /** The slot whose path attachment will be used to constrained the bones. */ public set slot (slotData: SlotData) { this._slot = slotData; } diff --git a/spine-ts/spine-core/src/PathConstraintPose.ts b/spine-ts/spine-core/src/PathConstraintPose.ts index f53e35151..ece200539 100644 --- a/spine-ts/spine-core/src/PathConstraintPose.ts +++ b/spine-ts/spine-core/src/PathConstraintPose.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose" +import type { Pose } from "./Pose" /** Stores a pose for a path constraint. */ export class PathConstraintPose implements Pose { diff --git a/spine-ts/spine-core/src/PhysicsConstraintData.ts b/spine-ts/spine-core/src/PhysicsConstraintData.ts index 8cadbf409..3526093fc 100644 --- a/spine-ts/spine-core/src/PhysicsConstraintData.ts +++ b/spine-ts/spine-core/src/PhysicsConstraintData.ts @@ -27,11 +27,11 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { BoneData } from "./BoneData.js"; +import type { BoneData } from "./BoneData.js"; import { ConstraintData } from "./ConstraintData.js"; import { PhysicsConstraint } from "./PhysicsConstraint.js"; import { PhysicsConstraintPose } from "./PhysicsConstraintPose.js"; -import { Skeleton } from "./Skeleton.js"; +import type { Skeleton } from "./Skeleton.js"; /** Stores the setup pose for a {@link PhysicsConstraint}. diff --git a/spine-ts/spine-core/src/PhysicsConstraintPose.ts b/spine-ts/spine-core/src/PhysicsConstraintPose.ts index 8aaefe21f..ccf9c8ccc 100644 --- a/spine-ts/spine-core/src/PhysicsConstraintPose.ts +++ b/spine-ts/spine-core/src/PhysicsConstraintPose.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose" +import type { Pose } from "./Pose" /** Stores a pose for a physics constraint. */ export class PhysicsConstraintPose implements Pose { diff --git a/spine-ts/spine-core/src/Posed.ts b/spine-ts/spine-core/src/Posed.ts index a5d32d95f..62501e22a 100644 --- a/spine-ts/spine-core/src/Posed.ts +++ b/spine-ts/spine-core/src/Posed.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose.js"; -import { PosedData } from "./PosedData.js"; +import type { Pose } from "./Pose.js"; +import type { PosedData } from "./PosedData.js"; export abstract class Posed< D extends PosedData

, - P extends Pose, + P extends Pose

, A extends P> { /** The constraint's setup pose data. */ diff --git a/spine-ts/spine-core/src/PosedActive.ts b/spine-ts/spine-core/src/PosedActive.ts index 700e04b8f..bf0786992 100644 --- a/spine-ts/spine-core/src/PosedActive.ts +++ b/spine-ts/spine-core/src/PosedActive.ts @@ -27,15 +27,15 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose.js"; +import type { Pose } from "./Pose.js"; import { Posed } from "./Posed.js"; -import { PosedData } from "./PosedData.js"; +import type { PosedData } from "./PosedData.js"; import type { Skeleton } from "./Skeleton"; export abstract class PosedActive< D extends PosedData

, - P extends Pose, + P extends Pose

, A extends P> extends Posed { diff --git a/spine-ts/spine-core/src/PosedData.ts b/spine-ts/spine-core/src/PosedData.ts index 07da7fed1..1533c212a 100644 --- a/spine-ts/spine-core/src/PosedData.ts +++ b/spine-ts/spine-core/src/PosedData.ts @@ -27,10 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose.js"; +import type { Pose } from "./Pose.js"; /** The base class for all constrained datas. */ -export abstract class PosedData

> { +export abstract class PosedData

> { /** The constraint's name, which is unique across all constraints in the skeleton of the same type. */ readonly name: string; diff --git a/spine-ts/spine-core/src/Skeleton.ts b/spine-ts/spine-core/src/Skeleton.ts index d3ea603ec..0ba5c4167 100644 --- a/spine-ts/spine-core/src/Skeleton.ts +++ b/spine-ts/spine-core/src/Skeleton.ts @@ -27,20 +27,20 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Attachment } from "./attachments/Attachment.js"; +import type { Attachment } from "./attachments/Attachment.js"; import { ClippingAttachment } from "./attachments/ClippingAttachment.js"; import { MeshAttachment } from "./attachments/MeshAttachment.js"; import { RegionAttachment } from "./attachments/RegionAttachment.js"; import { Bone } from "./Bone.js"; -import { Constraint } from "./Constraint.js"; -import { Physics } from "./Physics.js"; +import type { Constraint } from "./Constraint.js"; +import type { Physics } from "./Physics.js"; import { PhysicsConstraint } from "./PhysicsConstraint.js"; -import { Posed } from "./Posed.js"; -import { SkeletonClipping } from "./SkeletonClipping.js"; -import { SkeletonData } from "./SkeletonData.js"; -import { Skin } from "./Skin.js"; +import type { Posed } from "./Posed.js"; +import type { SkeletonClipping } from "./SkeletonClipping.js"; +import type { SkeletonData } from "./SkeletonData.js"; +import type { Skin } from "./Skin.js"; import { Slot } from "./Slot.js"; -import { Color, NumberArrayLike, Utils, Vector2 } from "./Utils.js"; +import { Color, type NumberArrayLike, Utils, Vector2 } from "./Utils.js"; /** Stores the current pose for a skeleton. * @@ -65,15 +65,18 @@ export class Skeleton { drawOrder: Array; /** The skeleton's constraints. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types readonly constraints: Array>; /** The skeleton's physics constraints. */ readonly physics: Array; /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link updateCache()}. */ - readonly _updateCache = new Array(); + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + readonly _updateCache = [] as any[]; - readonly resetCache: Array> = new Array(); + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + readonly resetCache: Array> = []; /** The skeleton's current skin. May be null. */ skin: Skin | null = null; @@ -125,30 +128,31 @@ export class Skeleton { if (!data) throw new Error("data cannot be null."); this.data = data; - this.bones = new Array(); + this.bones = [] as Bone[]; for (let i = 0; i < data.bones.length; i++) { - let boneData = data.bones[i]; + const boneData = data.bones[i]; let bone: Bone; if (!boneData.parent) bone = new Bone(boneData, null); else { - let parent = this.bones[boneData.parent.index]; + const parent = this.bones[boneData.parent.index]; bone = new Bone(boneData, parent); parent.children.push(bone); } this.bones.push(bone); } - this.slots = new Array(); - this.drawOrder = new Array(); + this.slots = [] as Slot[]; + this.drawOrder = [] as Slot[]; for (const slotData of this.data.slots) { - let slot = new Slot(slotData, this); + const slot = new Slot(slotData, this); this.slots.push(slot); this.drawOrder.push(slot); } - this.physics = new Array(); - this.constraints = new Array>(); + this.physics = [] as PhysicsConstraint[]; + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + this.constraints = [] as Constraint[]; for (const constraintData of this.data.constraints) { const constraint = constraintData.create(this); if (constraint instanceof PhysicsConstraint) this.physics.push(constraint); @@ -166,20 +170,20 @@ export class Skeleton { this._updateCache.length = 0; this.resetCache.length = 0; - let slots = this.slots; + const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) slots[i].usePose(); - let bones = this.bones; + const bones = this.bones; const boneCount = bones.length; for (let i = 0, n = boneCount; i < n; i++) { - let bone = bones[i]; + const bone = bones[i]; bone.sorted = bone.data.skinRequired; bone.active = !bone.sorted; bone.usePose(); } if (this.skin) { - let skinBones = this.skin.bones; + const skinBones = this.skin.bones; for (let i = 0, n = this.skin.bones.length; i < n; i++) { let bone: Bone | null = this.bones[skinBones[i].index]; do { @@ -190,13 +194,14 @@ export class Skeleton { } } - let constraints = this.constraints; + const constraints = this.constraints; let n = this.constraints.length; for (let i = 0; i < n; i++) constraints[i].usePose(); for (let i = 0; i < n; i++) { const constraint = constraints[i]; constraint.active = constraint.isSourceActive() + // biome-ignore lint/complexity/useOptionalChain: changing to this might return undefined && (!constraint.data.skinRequired || (this.skin != null && this.skin.constraints.includes(constraint.data))); if (constraint.active) constraint.sort(this); } @@ -212,6 +217,7 @@ export class Skeleton { } + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types constrained (object: Posed) { if (object.pose === object.applied) { object.useConstrained(); @@ -221,7 +227,7 @@ export class Skeleton { sortBone (bone: Bone) { if (bone.sorted || !bone.active) return; - let parent = bone.parent; + const parent = bone.parent; if (parent) this.sortBone(parent); bone.sorted = true; this._updateCache.push(bone); @@ -229,7 +235,7 @@ export class Skeleton { sortReset (bones: Array) { for (let i = 0, n = bones.length; i < n; i++) { - let bone = bones[i]; + const bone = bones[i]; if (bone.active) { if (bone.sorted) this.sortReset(bone.children); bone.sorted = false; @@ -272,7 +278,7 @@ export class Skeleton { /** Sets the slots and draw order to their setup pose values. */ setupPoseSlots () { - let slots = this.slots; + const slots = this.slots; Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); for (let i = 0, n = slots.length; i < n; i++) slots[i].setupPose(); @@ -280,7 +286,7 @@ export class Skeleton { /** Returns the root bone, or null if the skeleton has no bones. */ getRootBone () { - if (this.bones.length == 0) return null; + if (this.bones.length === 0) return null; return this.bones[0]; } @@ -288,9 +294,9 @@ export class Skeleton { * repeatedly. */ findBone (boneName: string) { if (!boneName) throw new Error("boneName cannot be null."); - let bones = this.bones; + const bones = this.bones; for (let i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; + if (bones[i].data.name === boneName) return bones[i]; return null; } @@ -298,9 +304,9 @@ export class Skeleton { * repeatedly. */ findSlot (slotName: string) { if (!slotName) throw new Error("slotName cannot be null."); - let slots = this.slots; + const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; + if (slots[i].data.name === slotName) return slots[i]; return null; } @@ -328,23 +334,23 @@ export class Skeleton { }; private setSkinByName (skinName: string) { - let skin = this.data.findSkin(skinName); - if (!skin) throw new Error("Skin not found: " + skinName); + const skin = this.data.findSkin(skinName); + if (!skin) throw new Error(`Skin not found: ${skinName}`); this.setSkin(skin); } private setSkinBySkin (newSkin: Skin | null) { - if (newSkin == this.skin) return; + if (newSkin === this.skin) return; if (newSkin) { if (this.skin) newSkin.attachAll(this, this.skin); else { - let slots = this.slots; + const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) { - let slot = slots[i]; - let name = slot.data.attachmentName; + const slot = slots[i]; + const name = slot.data.attachmentName; if (name) { - let attachment = newSkin.getAttachment(i, name); + const attachment = newSkin.getAttachment(i, name); if (attachment) slot.pose.setAttachment(attachment); } } @@ -378,7 +384,7 @@ export class Skeleton { * See {@link #getAttachment()}. * @returns May be null. */ private getAttachmentByName (slotName: string, attachmentName: string): Attachment | null { - let slot = this.data.findSlot(slotName); + const slot = this.data.findSlot(slotName); if (!slot) throw new Error(`Can't find slot with name ${slotName}`); return this.getAttachment(slot.index, attachmentName); } @@ -391,7 +397,7 @@ export class Skeleton { private getAttachmentByIndex (slotIndex: number, attachmentName: string): Attachment | null { if (!attachmentName) throw new Error("attachmentName cannot be null."); if (this.skin) { - let attachment = this.skin.getAttachment(slotIndex, attachmentName); + const attachment = this.skin.getAttachment(slotIndex, attachmentName); if (attachment) return attachment; } if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); @@ -404,16 +410,17 @@ export class Skeleton { setAttachment (slotName: string, attachmentName: string) { if (!slotName) throw new Error("slotName cannot be null."); const slot = this.findSlot(slotName); - if (!slot) throw new Error("Slot not found: " + slotName); + if (!slot) throw new Error(`Slot not found: ${slotName}`); let attachment: Attachment | null = null; if (attachmentName) { attachment = this.getAttachment(slot.data.index, attachmentName); if (!attachment) - throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + throw new Error(`Attachment not found: ${attachmentName}, for slot: ${slotName}`); } slot.pose.setAttachment(attachment); } + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types findConstraint> (constraintName: string, type: new () => T): T | null { if (constraintName == null) throw new Error("constraintName cannot be null."); if (type == null) throw new Error("type cannot be null."); @@ -428,8 +435,8 @@ export class Skeleton { /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`. * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */ getBoundsRect (clipper?: SkeletonClipping) { - let offset = new Vector2(); - let size = new Vector2(); + const offset = new Vector2(); + const size = new Vector2(); this.getBounds(offset, size, undefined, clipper); return { x: offset.x, y: offset.y, width: size.x, height: size.y }; } @@ -442,15 +449,15 @@ export class Skeleton { getBounds (offset: Vector2, size: Vector2, temp: Array = new Array(2), clipper: SkeletonClipping | null = null) { if (!offset) throw new Error("offset cannot be null."); if (!size) throw new Error("size cannot be null."); - let drawOrder = this.drawOrder; + const drawOrder = this.drawOrder; let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; for (let i = 0, n = drawOrder.length; i < n; i++) { - let slot = drawOrder[i]; + const slot = drawOrder[i]; if (!slot.bone.active) continue; let verticesLength = 0; let vertices: NumberArrayLike | null = null; let triangles: NumberArrayLike | null = null; - let attachment = slot.pose.attachment; + const attachment = slot.pose.attachment; if (attachment) { if (attachment instanceof RegionAttachment) { verticesLength = 8; @@ -468,12 +475,12 @@ export class Skeleton { continue; } if (vertices && triangles) { - if (clipper && clipper.isClipping() && clipper.clipTriangles(vertices, triangles, triangles.length)) { + if (clipper?.isClipping() && clipper.clipTriangles(vertices, triangles, triangles.length)) { vertices = clipper.clippedVertices; verticesLength = clipper.clippedVertices.length; } for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { - let x = vertices[ii], y = vertices[ii + 1]; + const x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); diff --git a/spine-ts/spine-core/src/SkeletonBinary.ts b/spine-ts/spine-core/src/SkeletonBinary.ts index 1e4228a5c..04c6c59f0 100644 --- a/spine-ts/spine-core/src/SkeletonBinary.ts +++ b/spine-ts/spine-core/src/SkeletonBinary.ts @@ -27,25 +27,24 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { AlphaTimeline, Animation, AttachmentTimeline, BoneTimeline2, CurveTimeline, CurveTimeline1, DeformTimeline, DrawOrderTimeline, EventTimeline, IkConstraintTimeline, InheritTimeline, PathConstraintMixTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintMixTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintWindTimeline, RGB2Timeline, RGBA2Timeline, RGBATimeline, RGBTimeline, RotateTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, SequenceTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, SliderMixTimeline, SliderTimeline, Timeline, TransformConstraintTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline } from "./Animation.js"; -import { Attachment, VertexAttachment } from "./attachments/Attachment.js"; -import { AttachmentLoader } from "./attachments/AttachmentLoader.js"; -import { HasTextureRegion } from "./attachments/HasTextureRegion.js"; -import { MeshAttachment } from "./attachments/MeshAttachment.js"; +import { AlphaTimeline, Animation, AttachmentTimeline, type BoneTimeline2, type CurveTimeline, CurveTimeline1, DeformTimeline, DrawOrderTimeline, EventTimeline, IkConstraintTimeline, InheritTimeline, PathConstraintMixTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintMixTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintWindTimeline, RGB2Timeline, RGBA2Timeline, RGBATimeline, RGBTimeline, RotateTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, SequenceTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, SliderMixTimeline, SliderTimeline, type Timeline, TransformConstraintTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline } from "./Animation.js"; +import type { Attachment, VertexAttachment } from "./attachments/Attachment.js"; +import type { AttachmentLoader } from "./attachments/AttachmentLoader.js"; +import type { HasTextureRegion } from "./attachments/HasTextureRegion.js"; +import type { MeshAttachment } from "./attachments/MeshAttachment.js"; import { Sequence, SequenceModeValues } from "./attachments/Sequence.js"; import { BoneData } from "./BoneData.js"; import { Event } from "./Event.js"; import { EventData } from "./EventData.js"; import { IkConstraintData } from "./IkConstraintData.js"; -import { PathConstraint } from "./PathConstraint.js"; import { PathConstraintData, PositionMode, SpacingMode } from "./PathConstraintData.js"; import { PhysicsConstraintData } from "./PhysicsConstraintData.js"; import { SkeletonData } from "./SkeletonData.js"; import { Skin } from "./Skin.js"; import { SliderData } from "./SliderData.js"; import { SlotData } from "./SlotData.js"; -import { FromProperty, FromRotate, FromScaleX, FromScaleY, FromShearY, FromX, FromY, ToProperty, ToRotate, ToScaleX, ToScaleY, ToShearY, ToX, ToY, TransformConstraintData } from "./TransformConstraintData.js"; -import { Color, Utils } from "./Utils.js"; +import { type FromProperty, FromRotate, FromScaleX, FromScaleY, FromShearY, FromX, FromY, type ToProperty, ToRotate, ToScaleX, ToScaleY, ToShearY, ToX, ToY, TransformConstraintData } from "./TransformConstraintData.js"; +import { Color, type NumberArrayLike, Utils } from "./Utils.js"; /** Loads skeleton data in the Spine binary format. * @@ -60,23 +59,23 @@ export class SkeletonBinary { scale = 1; attachmentLoader: AttachmentLoader; - private linkedMeshes = new Array(); + private linkedMeshes = [] as LinkedMesh[]; constructor (attachmentLoader: AttachmentLoader) { this.attachmentLoader = attachmentLoader; } readSkeletonData (binary: Uint8Array | ArrayBuffer): SkeletonData { - let scale = this.scale; + const scale = this.scale; - let skeletonData = new SkeletonData(); + const skeletonData = new SkeletonData(); skeletonData.name = ""; // BOZO - let input = new BinaryInput(binary); + const input = new BinaryInput(binary); - let lowHash = input.readInt32(); - let highHash = input.readInt32(); - skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + const lowHash = input.readInt32(); + const highHash = input.readInt32(); + skeletonData.hash = highHash === 0 && lowHash === 0 ? null : highHash.toString(16) + lowHash.toString(16); skeletonData.version = input.readString(); skeletonData.x = input.readFloat(); skeletonData.y = input.readFloat(); @@ -84,7 +83,7 @@ export class SkeletonBinary { skeletonData.height = input.readFloat(); skeletonData.referenceScale = input.readFloat() * scale; - let nonessential = input.readBoolean(); + const nonessential = input.readBoolean(); if (nonessential) { skeletonData.fps = input.readFloat(); skeletonData.imagesPath = input.readString(); @@ -95,7 +94,7 @@ export class SkeletonBinary { // Strings. n = input.readInt(true) for (let i = 0; i < n; i++) { - let str = input.readString(); + const str = input.readString(); if (!str) throw new Error("String in string table must not be null."); input.strings.push(str); } @@ -104,10 +103,10 @@ export class SkeletonBinary { const bones = skeletonData.bones; n = input.readInt(true) for (let i = 0; i < n; i++) { - let name = input.readString(); + const name = input.readString(); if (!name) throw new Error("Bone name must not be null."); - let parent = i == 0 ? null : bones[input.readInt(true)]; - let data = new BoneData(i, name, parent); + const parent = i === 0 ? null : bones[input.readInt(true)]; + const data = new BoneData(i, name, parent); const setup = data.setup; setup.rotation = input.readFloat(); setup.x = input.readFloat() * scale; @@ -130,14 +129,14 @@ export class SkeletonBinary { // Slots. n = input.readInt(true); for (let i = 0; i < n; i++) { - let slotName = input.readString(); + const slotName = input.readString(); if (!slotName) throw new Error("Slot name must not be null."); - let boneData = bones[input.readInt(true)]; - let data = new SlotData(i, slotName, boneData); + const boneData = bones[input.readInt(true)]; + const data = new SlotData(i, slotName, boneData); Color.rgba8888ToColor(data.setup.color, input.readInt32()); - let darkColor = input.readInt32(); - if (darkColor != -1) Color.rgb888ToColor(data.setup.darkColor = new Color(), darkColor); + const darkColor = input.readInt32(); + if (darkColor !== -1) Color.rgb888ToColor(data.setup.darkColor = new Color(), darkColor); data.attachmentName = input.readStringRef(); data.blendMode = input.readInt(true); @@ -149,43 +148,43 @@ export class SkeletonBinary { const constraints = skeletonData.constraints; const constraintCount = input.readInt(true); for (let i = 0; i < constraintCount; i++) { - let name = input.readString(); + const name = input.readString(); if (!name) throw new Error("Constraint data name must not be null."); - let nn; + let nn: number; switch (input.readByte()) { case CONSTRAINT_IK: { - let data = new IkConstraintData(name); + const data = new IkConstraintData(name); nn = input.readInt(true); for (let ii = 0; ii < nn; ii++) data.bones.push(bones[input.readInt(true)]); data.target = bones[input.readInt(true)]; - let flags = input.readByte(); - data.skinRequired = (flags & 1) != 0; - data.uniform = (flags & 2) != 0; + const flags = input.readByte(); + data.skinRequired = (flags & 1) !== 0; + data.uniform = (flags & 2) !== 0; const setup = data.setup; - setup.bendDirection = (flags & 4) != 0 ? -1 : 1; - setup.compress = (flags & 8) != 0; - setup.stretch = (flags & 16) != 0; - if ((flags & 32) != 0) setup.mix = (flags & 64) != 0 ? input.readFloat() : 1; - if ((flags & 128) != 0) setup.softness = input.readFloat() * scale; + setup.bendDirection = (flags & 4) !== 0 ? -1 : 1; + setup.compress = (flags & 8) !== 0; + setup.stretch = (flags & 16) !== 0; + if ((flags & 32) !== 0) setup.mix = (flags & 64) !== 0 ? input.readFloat() : 1; + if ((flags & 128) !== 0) setup.softness = input.readFloat() * scale; constraints.push(data); break; } case CONSTRAINT_TRANSFORM: { - let data = new TransformConstraintData(name); + const data = new TransformConstraintData(name); nn = input.readInt(true); for (let ii = 0; ii < nn; ii++) data.bones.push(bones[input.readInt(true)]); data.source = bones[input.readInt(true)]; let flags = input.readUnsignedByte(); - data.skinRequired = (flags & 1) != 0; - data.localSource = (flags & 2) != 0; - data.localTarget = (flags & 4) != 0; - data.additive = (flags & 8) != 0; - data.clamp = (flags & 16) != 0; + data.skinRequired = (flags & 1) !== 0; + data.localSource = (flags & 2) !== 0; + data.localTarget = (flags & 4) !== 0; + data.additive = (flags & 8) !== 0; + data.clamp = (flags & 16) !== 0; nn = flags >> 5; - for (let ii = 0, tn; ii < nn; ii++) { + for (let ii = 0, tn: number; ii < nn; ii++) { let fromScale = 1; let from: FromProperty | null; switch (input.readByte()) { @@ -237,40 +236,40 @@ export class SkeletonBinary { data.properties[ii] = from; } flags = input.readByte(); - if ((flags & 1) != 0) data.offsets[TransformConstraintData.ROTATION] = input.readFloat(); - if ((flags & 2) != 0) data.offsets[TransformConstraintData.X] = input.readFloat() * scale; - if ((flags & 4) != 0) data.offsets[TransformConstraintData.Y] = input.readFloat() * scale; - if ((flags & 8) != 0) data.offsets[TransformConstraintData.SCALEX] = input.readFloat(); - if ((flags & 16) != 0) data.offsets[TransformConstraintData.SCALEY] = input.readFloat(); - if ((flags & 32) != 0) data.offsets[TransformConstraintData.SHEARY] = input.readFloat(); + if ((flags & 1) !== 0) data.offsets[TransformConstraintData.ROTATION] = input.readFloat(); + if ((flags & 2) !== 0) data.offsets[TransformConstraintData.X] = input.readFloat() * scale; + if ((flags & 4) !== 0) data.offsets[TransformConstraintData.Y] = input.readFloat() * scale; + if ((flags & 8) !== 0) data.offsets[TransformConstraintData.SCALEX] = input.readFloat(); + if ((flags & 16) !== 0) data.offsets[TransformConstraintData.SCALEY] = input.readFloat(); + if ((flags & 32) !== 0) data.offsets[TransformConstraintData.SHEARY] = input.readFloat(); flags = input.readByte(); const setup = data.setup; - if ((flags & 1) != 0) setup.mixRotate = input.readFloat(); - if ((flags & 2) != 0) setup.mixX = input.readFloat(); - if ((flags & 4) != 0) setup.mixY = input.readFloat(); - if ((flags & 8) != 0) setup.mixScaleX = input.readFloat(); - if ((flags & 16) != 0) setup.mixScaleY = input.readFloat(); - if ((flags & 32) != 0) setup.mixShearY = input.readFloat(); + if ((flags & 1) !== 0) setup.mixRotate = input.readFloat(); + if ((flags & 2) !== 0) setup.mixX = input.readFloat(); + if ((flags & 4) !== 0) setup.mixY = input.readFloat(); + if ((flags & 8) !== 0) setup.mixScaleX = input.readFloat(); + if ((flags & 16) !== 0) setup.mixScaleY = input.readFloat(); + if ((flags & 32) !== 0) setup.mixShearY = input.readFloat(); constraints.push(data); break; } case CONSTRAINT_PATH: { - let data = new PathConstraintData(name); + const data = new PathConstraintData(name); nn = input.readInt(true); for (let ii = 0; ii < nn; ii++) data.bones.push(bones[input.readInt(true)]); data.slot = skeletonData.slots[input.readInt(true)]; const flags = input.readByte(); - data.skinRequired = (flags & 1) != 0; + data.skinRequired = (flags & 1) !== 0; data.positionMode = (flags >> 1) & 2; data.spacingMode = (flags >> 2) & 3; data.rotateMode = (flags >> 4) & 3; - if ((flags & 128) != 0) data.offsetRotation = input.readFloat(); + if ((flags & 128) !== 0) data.offsetRotation = input.readFloat(); const setup = data.setup; setup.position = input.readFloat(); - if (data.positionMode == PositionMode.Fixed) setup.position *= scale; + if (data.positionMode === PositionMode.Fixed) setup.position *= scale; setup.spacing = input.readFloat(); - if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) setup.spacing *= scale; + if (data.spacingMode === SpacingMode.Length || data.spacingMode === SpacingMode.Fixed) setup.spacing *= scale; setup.mixRotate = input.readFloat(); setup.mixX = input.readFloat(); setup.mixY = input.readFloat(); @@ -281,45 +280,45 @@ export class SkeletonBinary { const data = new PhysicsConstraintData(name); data.bone = bones[input.readInt(true)]; let flags = input.readByte(); - data.skinRequired = (flags & 1) != 0; - if ((flags & 2) != 0) data.x = input.readFloat(); - if ((flags & 4) != 0) data.y = input.readFloat(); - if ((flags & 8) != 0) data.rotate = input.readFloat(); - if ((flags & 16) != 0) data.scaleX = input.readFloat(); - if ((flags & 32) != 0) data.shearX = input.readFloat(); - data.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale; + data.skinRequired = (flags & 1) !== 0; + if ((flags & 2) !== 0) data.x = input.readFloat(); + if ((flags & 4) !== 0) data.y = input.readFloat(); + if ((flags & 8) !== 0) data.rotate = input.readFloat(); + if ((flags & 16) !== 0) data.scaleX = input.readFloat(); + if ((flags & 32) !== 0) data.shearX = input.readFloat(); + data.limit = ((flags & 64) !== 0 ? input.readFloat() : 5000) * scale; data.step = 1 / input.readUnsignedByte(); const setup = data.setup; setup.inertia = input.readFloat(); setup.strength = input.readFloat(); setup.damping = input.readFloat(); - setup.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + setup.massInverse = (flags & 128) !== 0 ? input.readFloat() : 1; setup.wind = input.readFloat(); setup.gravity = input.readFloat(); flags = input.readByte(); - if ((flags & 1) != 0) data.inertiaGlobal = true; - if ((flags & 2) != 0) data.strengthGlobal = true; - if ((flags & 4) != 0) data.dampingGlobal = true; - if ((flags & 8) != 0) data.massGlobal = true; - if ((flags & 16) != 0) data.windGlobal = true; - if ((flags & 32) != 0) data.gravityGlobal = true; - if ((flags & 64) != 0) data.mixGlobal = true; - setup.mix = (flags & 128) != 0 ? input.readFloat() : 1; + if ((flags & 1) !== 0) data.inertiaGlobal = true; + if ((flags & 2) !== 0) data.strengthGlobal = true; + if ((flags & 4) !== 0) data.dampingGlobal = true; + if ((flags & 8) !== 0) data.massGlobal = true; + if ((flags & 16) !== 0) data.windGlobal = true; + if ((flags & 32) !== 0) data.gravityGlobal = true; + if ((flags & 64) !== 0) data.mixGlobal = true; + setup.mix = (flags & 128) !== 0 ? input.readFloat() : 1; constraints.push(data); break; } case CONSTRAINT_SLIDER: { const data = new SliderData(name); const flags = input.readByte(); - data.skinRequired = (flags & 1) != 0; - data.loop = (flags & 2) != 0; - data.additive = (flags & 4) != 0; - if ((flags & 8) != 0) data.setup.time = input.readFloat(); - if ((flags & 16) != 0) data.setup.mix = (flags & 32) != 0 ? input.readFloat() : 1; - if ((flags & 64) != 0) { - data.local = (flags & 128) != 0; + data.skinRequired = (flags & 1) !== 0; + data.loop = (flags & 2) !== 0; + data.additive = (flags & 4) !== 0; + if ((flags & 8) !== 0) data.setup.time = input.readFloat(); + if ((flags & 16) !== 0) data.setup.mix = (flags & 32) !== 0 ? input.readFloat() : 1; + if ((flags & 64) !== 0) { + data.local = (flags & 128) !== 0; data.bone = bones[input.readInt(true)]; - let offset = input.readFloat(); + const offset = input.readFloat(); let propertyScale = 1; switch (input.readByte()) { case 0: data.property = new FromRotate(); break; @@ -349,7 +348,7 @@ export class SkeletonBinary { } // Default skin. - let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + const defaultSkin = this.readSkin(input, skeletonData, true, nonessential); if (defaultSkin) { skeletonData.defaultSkin = defaultSkin; skeletonData.skins.push(defaultSkin); @@ -360,7 +359,7 @@ export class SkeletonBinary { let i = skeletonData.skins.length; Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); for (; i < n; i++) { - let skin = this.readSkin(input, skeletonData, false, nonessential); + const skin = this.readSkin(input, skeletonData, false, nonessential); if (!skin) throw new Error("readSkin() should not have returned null."); skeletonData.skins[i] = skin; } @@ -369,10 +368,10 @@ export class SkeletonBinary { // Linked meshes. n = this.linkedMeshes.length; for (let i = 0; i < n; i++) { - let linkedMesh = this.linkedMeshes[i]; + const linkedMesh = this.linkedMeshes[i]; const skin = skeletonData.skins[linkedMesh.skinIndex]; if (!linkedMesh.parent) throw new Error("Linked mesh parent must not be null"); - let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + const parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); if (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent as VertexAttachment : linkedMesh.mesh; linkedMesh.mesh.setParentMesh(parent as MeshAttachment); @@ -383,9 +382,9 @@ export class SkeletonBinary { // Events. n = input.readInt(true); for (let i = 0; i < n; i++) { - let eventName = input.readString(); + const eventName = input.readString(); if (!eventName) throw new Error("Event data name must not be null"); - let data = new EventData(eventName); + const data = new EventData(eventName); data.intValue = input.readInt(false); data.floatValue = input.readFloat(); data.stringValue = input.readString(); @@ -401,7 +400,7 @@ export class SkeletonBinary { const animations = skeletonData.animations; n = input.readInt(true); for (let i = 0; i < n; i++) { - let animationName = input.readString(); + const animationName = input.readString(); if (!animationName) throw new Error("Animation name must not be null."); animations.push(this.readAnimation(input, animationName, skeletonData)); } @@ -420,17 +419,17 @@ export class SkeletonBinary { if (defaultSkin) { slotCount = input.readInt(true) - if (slotCount == 0) return null; + if (slotCount === 0) return null; skin = new Skin("default"); } else { - let skinName = input.readString(); + const skinName = input.readString(); if (!skinName) throw new Error("Skin name must not be null."); skin = new Skin(skinName); if (nonessential) Color.rgba8888ToColor(skin.color, input.readInt32()); let n = input.readInt(true); - let from: Object[] = skeletonData.bones, to: Object[] = skin.bones; + let from: object[] = skeletonData.bones, to: object[] = skin.bones; for (let i = 0; i < n; i++) to[i] = from[input.readInt(true)]; @@ -444,12 +443,12 @@ export class SkeletonBinary { } for (let i = 0; i < slotCount; i++) { - let slotIndex = input.readInt(true); + const slotIndex = input.readInt(true); for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { - let name = input.readStringRef(); + const name = input.readStringRef(); if (!name) throw new Error("Attachment name must not be null"); - let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + const attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); if (attachment) skin.setAttachment(slotIndex, name, attachment); } } @@ -457,26 +456,26 @@ export class SkeletonBinary { } private readAttachment (input: BinaryInput, skeletonData: SkeletonData, skin: Skin, slotIndex: number, attachmentName: string | null | undefined, nonessential: boolean): Attachment | null { - let scale = this.scale; + const scale = this.scale; - let flags = input.readByte(); - const name = (flags & 8) != 0 ? input.readStringRef() : attachmentName; + const flags = input.readByte(); + const name = (flags & 8) !== 0 ? input.readStringRef() : attachmentName; if (!name) throw new Error("Attachment name must not be null"); switch ((flags & 0b111) as AttachmentType) { // BUG? case AttachmentType.Region: { - let path = (flags & 16) != 0 ? input.readStringRef() : null; - const color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff; - const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; - let rotation = (flags & 128) != 0 ? input.readFloat() : 0; - let x = input.readFloat(); - let y = input.readFloat(); - let scaleX = input.readFloat(); - let scaleY = input.readFloat(); - let width = input.readFloat(); - let height = input.readFloat(); + let path = (flags & 16) !== 0 ? input.readStringRef() : null; + const color = (flags & 32) !== 0 ? input.readInt32() : 0xffffffff; + const sequence = (flags & 64) !== 0 ? this.readSequence(input) : null; + const rotation = (flags & 128) !== 0 ? input.readFloat() : 0; + const x = input.readFloat(); + const y = input.readFloat(); + const scaleX = input.readFloat(); + const scaleY = input.readFloat(); + const width = input.readFloat(); + const height = input.readFloat(); if (!path) path = name; - let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + const region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); if (!region) return null; region.path = path; region.x = x * scale; @@ -492,23 +491,23 @@ export class SkeletonBinary { return region; } case AttachmentType.BoundingBox: { - let vertices = this.readVertices(input, (flags & 16) != 0); - let color = nonessential ? input.readInt32() : 0; + const vertices = this.readVertices(input, (flags & 16) !== 0); + const color = nonessential ? input.readInt32() : 0; - let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + const box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); if (!box) return null; box.worldVerticesLength = vertices.length; - box.vertices = vertices.vertices!; + box.vertices = vertices.vertices; box.bones = vertices.bones; if (nonessential) Color.rgba8888ToColor(box.color, color); return box; } case AttachmentType.Mesh: { - let path = (flags & 16) != 0 ? input.readStringRef() : name; - const color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff; - const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + let path = (flags & 16) !== 0 ? input.readStringRef() : name; + const color = (flags & 32) !== 0 ? input.readInt32() : 0xffffffff; + const sequence = (flags & 64) !== 0 ? this.readSequence(input) : null; const hullLength = input.readInt(true); - const vertices = this.readVertices(input, (flags & 128) != 0); + const vertices = this.readVertices(input, (flags & 128) !== 0); const uvs = this.readFloatArray(input, vertices.length, 1); const triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3); let edges: number[] = []; @@ -520,12 +519,12 @@ export class SkeletonBinary { } if (!path) path = name; - let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + const mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); if (!mesh) return null; mesh.path = path; Color.rgba8888ToColor(mesh.color, color); mesh.bones = vertices.bones; - mesh.vertices = vertices.vertices!; + mesh.vertices = vertices.vertices; mesh.worldVerticesLength = vertices.length; mesh.triangles = triangles; mesh.regionUVs = uvs; @@ -540,11 +539,11 @@ export class SkeletonBinary { return mesh; } case AttachmentType.LinkedMesh: { - const path = (flags & 16) != 0 ? input.readStringRef() : name; + const path = (flags & 16) !== 0 ? input.readStringRef() : name; if (path == null) throw new Error("Path of linked mesh must not be null"); - const color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff; - const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; - const inheritTimelines = (flags & 128) != 0; + const color = (flags & 32) !== 0 ? input.readInt32() : 0xffffffff; + const sequence = (flags & 64) !== 0 ? this.readSequence(input) : null; + const inheritTimelines = (flags & 128) !== 0; const skinIndex = input.readInt(true); const parent = input.readStringRef(); let width = 0, height = 0; @@ -553,7 +552,7 @@ export class SkeletonBinary { height = input.readFloat(); } - let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + const mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); if (!mesh) return null; mesh.path = path; Color.rgba8888ToColor(mesh.color, color); @@ -566,9 +565,9 @@ export class SkeletonBinary { return mesh; } case AttachmentType.Path: { - const closed = (flags & 16) != 0; - const constantSpeed = (flags & 32) != 0; - const vertices = this.readVertices(input, (flags & 64) != 0); + const closed = (flags & 16) !== 0; + const constantSpeed = (flags & 32) !== 0; + const vertices = this.readVertices(input, (flags & 64) !== 0); const lengths = Utils.newArray(vertices.length / 6, 0); for (let i = 0, n = lengths.length; i < n; i++) @@ -580,7 +579,7 @@ export class SkeletonBinary { path.closed = closed; path.constantSpeed = constantSpeed; path.worldVerticesLength = vertices.length; - path.vertices = vertices.vertices!; + path.vertices = vertices.vertices; path.bones = vertices.bones; path.lengths = lengths; if (nonessential) Color.rgba8888ToColor(path.color, color); @@ -602,14 +601,14 @@ export class SkeletonBinary { } case AttachmentType.Clipping: { const endSlotIndex = input.readInt(true); - const vertices = this.readVertices(input, (flags & 16) != 0); - let color = nonessential ? input.readInt32() : 0; + const vertices = this.readVertices(input, (flags & 16) !== 0); + const color = nonessential ? input.readInt32() : 0; - let clip = this.attachmentLoader.newClippingAttachment(skin, name); + const clip = this.attachmentLoader.newClippingAttachment(skin, name); if (!clip) return null; clip.endSlot = skeletonData.slots[endSlotIndex]; clip.worldVerticesLength = vertices.length; - clip.vertices = vertices.vertices!; + clip.vertices = vertices.vertices; clip.bones = vertices.bones; if (nonessential) Color.rgba8888ToColor(clip.color, color); return clip; @@ -618,7 +617,7 @@ export class SkeletonBinary { } private readSequence (input: BinaryInput) { - let sequence = new Sequence(input.readInt(true)); + const sequence = new Sequence(input.readInt(true)); sequence.start = input.readInt(true); sequence.digits = input.readInt(true); sequence.setupIndex = input.readInt(true); @@ -628,16 +627,15 @@ export class SkeletonBinary { private readVertices (input: BinaryInput, weighted: boolean): Vertices { const scale = this.scale; const vertexCount = input.readInt(true); - const vertices = new Vertices(); - vertices.length = vertexCount << 1; - if (!weighted) { - vertices.vertices = this.readFloatArray(input, vertices.length, scale); - return vertices; - } - let weights = new Array(); - let bonesArray = new Array(); + const length = vertexCount << 1; + + if (!weighted) + return new Vertices(null, this.readFloatArray(input, length, scale), length); + + const weights: number[] = []; + const bonesArray: number[] = []; for (let i = 0; i < vertexCount; i++) { - let boneCount = input.readInt(true); + const boneCount = input.readInt(true); bonesArray.push(boneCount); for (let ii = 0; ii < boneCount; ii++) { bonesArray.push(input.readInt(true)); @@ -646,14 +644,12 @@ export class SkeletonBinary { weights.push(input.readFloat()); } } - vertices.vertices = Utils.toFloatArray(weights); - vertices.bones = bonesArray; - return vertices; + return new Vertices(bonesArray, Utils.toFloatArray(weights), length); } private readFloatArray (input: BinaryInput, n: number, scale: number): number[] { - let array = new Array(n); - if (scale == 1) { + const array = new Array(n); + if (scale === 1) { for (let i = 0; i < n; i++) array[i] = input.readFloat(); } else { @@ -664,7 +660,7 @@ export class SkeletonBinary { } private readShortArray (input: BinaryInput, n: number): number[] { - let array = new Array(n); + const array = new Array(n); for (let i = 0; i < n; i++) array[i] = input.readInt(true); return array; @@ -672,27 +668,27 @@ export class SkeletonBinary { private readAnimation (input: BinaryInput, name: string, skeletonData: SkeletonData): Animation { input.readInt(true); // Number of timelines. - let timelines = new Array(); - let scale = this.scale; + const timelines: Timeline[] = []; + const scale = this.scale; // Slot timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let slotIndex = input.readInt(true); + const slotIndex = input.readInt(true); for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { - let timelineType = input.readByte(); - let frameCount = input.readInt(true); - let frameLast = frameCount - 1; + const timelineType = input.readByte(); + const frameCount = input.readInt(true); + const frameLast = frameCount - 1; switch (timelineType) { case SLOT_ATTACHMENT: { - let timeline = new AttachmentTimeline(frameCount, slotIndex); + const timeline = new AttachmentTimeline(frameCount, slotIndex); for (let frame = 0; frame < frameCount; frame++) timeline.setFrame(frame, input.readFloat(), input.readStringRef()); timelines.push(timeline); break; } case SLOT_RGBA: { - let bezierCount = input.readInt(true); - let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + const bezierCount = input.readInt(true); + const timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); let time = input.readFloat(); let r = input.readUnsignedByte() / 255.0; @@ -702,13 +698,13 @@ export class SkeletonBinary { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, r, g, b, a); - if (frame == frameLast) break; + if (frame === frameLast) break; - let time2 = input.readFloat(); - let r2 = input.readUnsignedByte() / 255.0; - let g2 = input.readUnsignedByte() / 255.0; - let b2 = input.readUnsignedByte() / 255.0; - let a2 = input.readUnsignedByte() / 255.0; + const time2 = input.readFloat(); + const r2 = input.readUnsignedByte() / 255.0; + const g2 = input.readUnsignedByte() / 255.0; + const b2 = input.readUnsignedByte() / 255.0; + const a2 = input.readUnsignedByte() / 255.0; switch (input.readByte()) { case CURVE_STEPPED: @@ -730,8 +726,8 @@ export class SkeletonBinary { break; } case SLOT_RGB: { - let bezierCount = input.readInt(true); - let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + const bezierCount = input.readInt(true); + const timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); let time = input.readFloat(); let r = input.readUnsignedByte() / 255.0; @@ -740,12 +736,12 @@ export class SkeletonBinary { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, r, g, b); - if (frame == frameLast) break; + if (frame === frameLast) break; - let time2 = input.readFloat(); - let r2 = input.readUnsignedByte() / 255.0; - let g2 = input.readUnsignedByte() / 255.0; - let b2 = input.readUnsignedByte() / 255.0; + const time2 = input.readFloat(); + const r2 = input.readUnsignedByte() / 255.0; + const g2 = input.readUnsignedByte() / 255.0; + const b2 = input.readUnsignedByte() / 255.0; switch (input.readByte()) { case CURVE_STEPPED: @@ -765,8 +761,8 @@ export class SkeletonBinary { break; } case SLOT_RGBA2: { - let bezierCount = input.readInt(true); - let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + const bezierCount = input.readInt(true); + const timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); let time = input.readFloat(); let r = input.readUnsignedByte() / 255.0; @@ -779,15 +775,15 @@ export class SkeletonBinary { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); - if (frame == frameLast) break; - let time2 = input.readFloat(); - let nr = input.readUnsignedByte() / 255.0; - let ng = input.readUnsignedByte() / 255.0; - let nb = input.readUnsignedByte() / 255.0; - let na = input.readUnsignedByte() / 255.0; - let nr2 = input.readUnsignedByte() / 255.0; - let ng2 = input.readUnsignedByte() / 255.0; - let nb2 = input.readUnsignedByte() / 255.0; + if (frame === frameLast) break; + const time2 = input.readFloat(); + const nr = input.readUnsignedByte() / 255.0; + const ng = input.readUnsignedByte() / 255.0; + const nb = input.readUnsignedByte() / 255.0; + const na = input.readUnsignedByte() / 255.0; + const nr2 = input.readUnsignedByte() / 255.0; + const ng2 = input.readUnsignedByte() / 255.0; + const nb2 = input.readUnsignedByte() / 255.0; switch (input.readByte()) { case CURVE_STEPPED: @@ -815,8 +811,8 @@ export class SkeletonBinary { break; } case SLOT_RGB2: { - let bezierCount = input.readInt(true); - let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + const bezierCount = input.readInt(true); + const timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); let time = input.readFloat(); let r = input.readUnsignedByte() / 255.0; @@ -828,14 +824,14 @@ export class SkeletonBinary { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, r, g, b, r2, g2, b2); - if (frame == frameLast) break; - let time2 = input.readFloat(); - let nr = input.readUnsignedByte() / 255.0; - let ng = input.readUnsignedByte() / 255.0; - let nb = input.readUnsignedByte() / 255.0; - let nr2 = input.readUnsignedByte() / 255.0; - let ng2 = input.readUnsignedByte() / 255.0; - let nb2 = input.readUnsignedByte() / 255.0; + if (frame === frameLast) break; + const time2 = input.readFloat(); + const nr = input.readUnsignedByte() / 255.0; + const ng = input.readUnsignedByte() / 255.0; + const nb = input.readUnsignedByte() / 255.0; + const nr2 = input.readUnsignedByte() / 255.0; + const ng2 = input.readUnsignedByte() / 255.0; + const nb2 = input.readUnsignedByte() / 255.0; switch (input.readByte()) { case CURVE_STEPPED: @@ -861,13 +857,13 @@ export class SkeletonBinary { break; } case SLOT_ALPHA: { - let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + const timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); let time = input.readFloat(), a = input.readUnsignedByte() / 255; for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, a); - if (frame == frameLast) break; - let time2 = input.readFloat(); - let a2 = input.readUnsignedByte() / 255; + if (frame === frameLast) break; + const time2 = input.readFloat(); + const a2 = input.readUnsignedByte() / 255; switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frame); @@ -886,18 +882,18 @@ export class SkeletonBinary { // Bone timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let boneIndex = input.readInt(true); + const boneIndex = input.readInt(true); for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { - let type = input.readByte(), frameCount = input.readInt(true); - if (type == BONE_INHERIT) { - let timeline = new InheritTimeline(frameCount, boneIndex); + const type = input.readByte(), frameCount = input.readInt(true); + if (type === BONE_INHERIT) { + const timeline = new InheritTimeline(frameCount, boneIndex); for (let frame = 0; frame < frameCount; frame++) { timeline.setFrame(frame, input.readFloat(), input.readByte()); } timelines.push(timeline); continue; } - let bezierCount = input.readInt(true); + const bezierCount = input.readInt(true); switch (type) { case BONE_ROTATE: readTimeline(input, timelines, new RotateTimeline(frameCount, bezierCount, boneIndex), 1); break; case BONE_TRANSLATE: readTimeline(input, timelines, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale); break; @@ -915,20 +911,20 @@ export class SkeletonBinary { // IK constraint timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; - let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + const index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + const timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); let flags = input.readByte(); - let time = input.readFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0; - let softness = (flags & 4) != 0 ? input.readFloat() * scale : 0; + let time = input.readFloat(), mix = (flags & 1) !== 0 ? ((flags & 2) !== 0 ? input.readFloat() : 1) : 0; + let softness = (flags & 4) !== 0 ? input.readFloat() * scale : 0; for (let frame = 0, bezier = 0; ; frame++) { - timeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); - if (frame == frameLast) break; + timeline.setFrame(frame, time, mix, softness, (flags & 8) !== 0 ? 1 : -1, (flags & 16) !== 0, (flags & 32) !== 0); + if (frame === frameLast) break; flags = input.readByte(); - const time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0; - const softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0; - if ((flags & 64) != 0) { + const time2 = input.readFloat(), mix2 = (flags & 1) !== 0 ? ((flags & 2) !== 0 ? input.readFloat() : 1) : 0; + const softness2 = (flags & 4) !== 0 ? input.readFloat() * scale : 0; + if ((flags & 64) !== 0) { timeline.setStepped(frame); - } else if ((flags & 128) != 0) { + } else if ((flags & 128) !== 0) { setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); } @@ -941,14 +937,14 @@ export class SkeletonBinary { // Transform constraint timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; - let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + const index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + const timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); - if (frame == frameLast) break; - let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), + if (frame === frameLast) break; + const time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); switch (input.readByte()) { case CURVE_STEPPED: @@ -975,26 +971,26 @@ export class SkeletonBinary { // Path constraint timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let index = input.readInt(true); - let data = skeletonData.constraints[index] as PathConstraintData; + const index = input.readInt(true); + const data = skeletonData.constraints[index] as PathConstraintData; for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); switch (type) { case PATH_POSITION: readTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index), - data.positionMode == PositionMode.Fixed ? scale : 1); + data.positionMode === PositionMode.Fixed ? scale : 1); break; case PATH_SPACING: readTimeline(input, timelines, new PathConstraintSpacingTimeline(frameCount, bezierCount, index), - data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1); + data.spacingMode === SpacingMode.Length || data.spacingMode === SpacingMode.Fixed ? scale : 1); break; - case PATH_MIX: - let timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + case PATH_MIX: { + const timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { timeline.setFrame(frame, time, mixRotate, mixX, mixY); - if (frame == frameLast) break; - let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), + if (frame === frameLast) break; + const time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); switch (input.readByte()) { case CURVE_STEPPED: @@ -1011,6 +1007,7 @@ export class SkeletonBinary { mixY = mixY2; } timelines.push(timeline); + } } } } @@ -1020,7 +1017,7 @@ export class SkeletonBinary { const index = input.readInt(true) - 1; for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { const type = input.readByte(), frameCount = input.readInt(true); - if (type == PHYSICS_RESET) { + if (type === PHYSICS_RESET) { const timeline = new PhysicsConstraintResetTimeline(frameCount, index); for (let frame = 0; frame < frameCount; frame++) timeline.setFrame(frame, input.readFloat()); @@ -1049,7 +1046,7 @@ export class SkeletonBinary { switch (type) { case SLIDER_TIME: readTimeline(input, timelines, new SliderTimeline(frameCount, bezierCount, index), 1); break; case SLIDER_MIX: readTimeline(input, timelines, new SliderMixTimeline(frameCount, bezierCount, index), 1); break; - default: throw new Error("Uknown slider type: " + type); + default: throw new Error(`Uknown slider type: ${type}`); } } @@ -1057,39 +1054,39 @@ export class SkeletonBinary { // Attachment timelines. for (let i = 0, n = input.readInt(true); i < n; i++) { - let skin = skeletonData.skins[input.readInt(true)]; + const skin = skeletonData.skins[input.readInt(true)]; for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { - let slotIndex = input.readInt(true); + const slotIndex = input.readInt(true); for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { - let attachmentName = input.readStringRef(); + const attachmentName = input.readStringRef(); if (!attachmentName) throw new Error("attachmentName must not be null."); - let attachment = skin.getAttachment(slotIndex, attachmentName); - let timelineType = input.readByte(); - let frameCount = input.readInt(true); - let frameLast = frameCount - 1; + const attachment = skin.getAttachment(slotIndex, attachmentName); + const timelineType = input.readByte(); + const frameCount = input.readInt(true); + const frameLast = frameCount - 1; switch (timelineType) { case ATTACHMENT_DEFORM: { - let vertexAttachment = attachment as VertexAttachment; - let weighted = vertexAttachment.bones; - let vertices = vertexAttachment.vertices; - let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + const vertexAttachment = attachment as VertexAttachment; + const weighted = vertexAttachment.bones; + const vertices = vertexAttachment.vertices; + const deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; - let bezierCount = input.readInt(true); - let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + const bezierCount = input.readInt(true); + const timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); let time = input.readFloat(); for (let frame = 0, bezier = 0; ; frame++) { - let deform; + let deform: NumberArrayLike; let end = input.readInt(true); - if (end == 0) + if (end === 0) deform = weighted ? Utils.newFloatArray(deformLength) : vertices; else { deform = Utils.newFloatArray(deformLength); - let start = input.readInt(true); + const start = input.readInt(true); end += start; - if (scale == 1) { + if (scale === 1) { for (let v = start; v < end; v++) deform[v] = input.readFloat(); } else { @@ -1103,8 +1100,8 @@ export class SkeletonBinary { } timeline.setFrame(frame, time, deform); - if (frame == frameLast) break; - let time2 = input.readFloat(); + if (frame === frameLast) break; + const time2 = input.readFloat(); switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frame); @@ -1118,10 +1115,10 @@ export class SkeletonBinary { break; } case ATTACHMENT_SEQUENCE: { - let timeline = new SequenceTimeline(frameCount, slotIndex, attachment as unknown as HasTextureRegion); + const timeline = new SequenceTimeline(frameCount, slotIndex, attachment as unknown as HasTextureRegion); for (let frame = 0; frame < frameCount; frame++) { - let time = input.readFloat(); - let modeAndIndex = input.readInt32(); + const time = input.readFloat(); + const modeAndIndex = input.readInt32(); timeline.setFrame(frame, time, SequenceModeValues[modeAndIndex & 0xf], modeAndIndex >> 4, input.readFloat()); } @@ -1134,22 +1131,22 @@ export class SkeletonBinary { } // Draw order timeline. - let drawOrderCount = input.readInt(true); + const drawOrderCount = input.readInt(true); if (drawOrderCount > 0) { - let timeline = new DrawOrderTimeline(drawOrderCount); - let slotCount = skeletonData.slots.length; + const timeline = new DrawOrderTimeline(drawOrderCount); + const slotCount = skeletonData.slots.length; for (let i = 0; i < drawOrderCount; i++) { - let time = input.readFloat(); - let offsetCount = input.readInt(true); - let drawOrder = Utils.newArray(slotCount, 0); + const time = input.readFloat(); + const offsetCount = input.readInt(true); + const drawOrder = Utils.newArray(slotCount, 0); for (let ii = slotCount - 1; ii >= 0; ii--) drawOrder[ii] = -1; - let unchanged = Utils.newArray(slotCount - offsetCount, 0); + const unchanged = Utils.newArray(slotCount - offsetCount, 0); let originalIndex = 0, unchangedIndex = 0; for (let ii = 0; ii < offsetCount; ii++) { - let slotIndex = input.readInt(true); + const slotIndex = input.readInt(true); // Collect unchanged items. - while (originalIndex != slotIndex) + while (originalIndex !== slotIndex) unchanged[unchangedIndex++] = originalIndex++; // Set changed items. drawOrder[originalIndex + input.readInt(true)] = originalIndex++; @@ -1159,20 +1156,20 @@ export class SkeletonBinary { unchanged[unchangedIndex++] = originalIndex++; // Fill in unchanged items. for (let ii = slotCount - 1; ii >= 0; ii--) - if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + if (drawOrder[ii] === -1) drawOrder[ii] = unchanged[--unchangedIndex]; timeline.setFrame(i, time, drawOrder); } timelines.push(timeline); } // Event timeline. - let eventCount = input.readInt(true); + const eventCount = input.readInt(true); if (eventCount > 0) { - let timeline = new EventTimeline(eventCount); + const timeline = new EventTimeline(eventCount); for (let i = 0; i < eventCount; i++) { - let time = input.readFloat(); - let eventData = skeletonData.events[input.readInt(true)]; - let event = new Event(time, eventData); + const time = input.readFloat(); + const eventData = skeletonData.events[input.readInt(true)]; + const event = new Event(time, eventData); event.intValue = input.readInt(false); event.floatValue = input.readFloat(); event.stringValue = input.readString(); @@ -1194,7 +1191,7 @@ export class SkeletonBinary { } export class BinaryInput { - constructor (data: Uint8Array | ArrayBuffer, public strings = new Array(), private index: number = 0, private buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { + constructor (data: Uint8Array | ArrayBuffer, public strings = [] as string[], private index: number = 0, private buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { } readByte (): number { @@ -1206,13 +1203,13 @@ export class BinaryInput { } readShort (): number { - let value = this.buffer.getInt16(this.index); + const value = this.buffer.getInt16(this.index); this.index += 2; return value; } readInt32 (): number { - let value = this.buffer.getInt32(this.index) + const value = this.buffer.getInt32(this.index) this.index += 4; return value; } @@ -1220,16 +1217,16 @@ export class BinaryInput { readInt (optimizePositive: boolean) { let b = this.readByte(); let result = b & 0x7F; - if ((b & 0x80) != 0) { + if ((b & 0x80) !== 0) { b = this.readByte(); result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { + if ((b & 0x80) !== 0) { b = this.readByte(); result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { + if ((b & 0x80) !== 0) { b = this.readByte(); result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { + if ((b & 0x80) !== 0) { b = this.readByte(); result |= (b & 0x7F) << 28; } @@ -1240,8 +1237,8 @@ export class BinaryInput { } readStringRef (): string | null { - let index = this.readInt(true); - return index == 0 ? null : this.strings[index - 1]; + const index = this.readInt(true); + return index === 0 ? null : this.strings[index - 1]; } readString (): string | null { @@ -1254,9 +1251,8 @@ export class BinaryInput { } byteCount--; let chars = ""; - let charCount = 0; for (let i = 0; i < byteCount;) { - let b = this.readUnsignedByte(); + const b = this.readUnsignedByte(); switch (b >> 4) { case 12: case 13: @@ -1276,13 +1272,13 @@ export class BinaryInput { } readFloat (): number { - let value = this.buffer.getFloat32(this.index); + const value = this.buffer.getFloat32(this.index); this.index += 4; return value; } readBoolean (): boolean { - return this.readByte() != 0; + return this.readByte() !== 0; } } @@ -1302,7 +1298,7 @@ class LinkedMesh { } class Vertices { - constructor (public bones: Array | null = null, public vertices: Array | Float32Array | null = null, public length: number = 0) { } + constructor (public bones: Array | null = null, public vertices: Array | Float32Array, public length: number = 0) { } } enum AttachmentType { Region, BoundingBox, Mesh, LinkedMesh, Path, Point, Clipping } @@ -1320,8 +1316,8 @@ function readTimeline1 (input: BinaryInput, timelines: Array, timeline let time = input.readFloat(), value = input.readFloat() * scale; for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { timeline.setFrame(frame, time, value); - if (frame == frameLast) break; - let time2 = input.readFloat(), value2 = input.readFloat() * scale; + if (frame === frameLast) break; + const time2 = input.readFloat(), value2 = input.readFloat() * scale; switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frame); @@ -1339,8 +1335,8 @@ function readTimeline2 (input: BinaryInput, timelines: Array, timeline let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { timeline.setFrame(frame, time, value1, value2); - if (frame == frameLast) break; - let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + if (frame === frameLast) break; + const time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frame); @@ -1405,6 +1401,7 @@ const PHYSICS_RESET = 8; const SLIDER_TIME = 0; const SLIDER_MIX = 1; +// biome-ignore lint/correctness/noUnusedVariables: intentional const CURVE_LINEAR = 0; const CURVE_STEPPED = 1; const CURVE_BEZIER = 2; diff --git a/spine-ts/spine-core/src/SkeletonBounds.ts b/spine-ts/spine-core/src/SkeletonBounds.ts index 3a6352890..d01c085c4 100644 --- a/spine-ts/spine-core/src/SkeletonBounds.ts +++ b/spine-ts/spine-core/src/SkeletonBounds.ts @@ -28,8 +28,8 @@ *****************************************************************************/ import { BoundingBoxAttachment } from "./attachments/BoundingBoxAttachment.js"; -import { Skeleton } from "./Skeleton.js"; -import { NumberArrayLike, Pool, Utils } from "./Utils.js"; +import type { Skeleton } from "./Skeleton.js"; +import { type NumberArrayLike, Pool, Utils } from "./Utils.js"; /** Collects each visible {@link BoundingBoxAttachment} and computes the world vertices for its polygon. The polygon vertices are * provided along with convenience methods for doing hit detection. */ @@ -48,10 +48,10 @@ export class SkeletonBounds { maxY = 0; /** The visible bounding boxes. */ - boundingBoxes = new Array(); + boundingBoxes = [] as BoundingBoxAttachment[]; /** The world vertices for the bounding box polygons. */ - polygons = new Array(); + polygons = [] as NumberArrayLike[]; private polygonPool = new Pool(() => { return Utils.newFloatArray(16); @@ -63,25 +63,25 @@ export class SkeletonBounds { * SkeletonBounds AABB methods will always return true. */ update (skeleton: Skeleton, updateAabb: boolean) { if (!skeleton) throw new Error("skeleton cannot be null."); - let boundingBoxes = this.boundingBoxes; - let polygons = this.polygons; - let polygonPool = this.polygonPool; - let slots = skeleton.slots; - let slotCount = slots.length; + const boundingBoxes = this.boundingBoxes; + const polygons = this.polygons; + const polygonPool = this.polygonPool; + const slots = skeleton.slots; + const slotCount = slots.length; boundingBoxes.length = 0; polygonPool.freeAll(polygons); polygons.length = 0; for (let i = 0; i < slotCount; i++) { - let slot = slots[i]; + const slot = slots[i]; if (!slot.bone.active) continue; - let attachment = slot.applied.attachment; + const attachment = slot.applied.attachment; if (attachment instanceof BoundingBoxAttachment) { boundingBoxes.push(attachment); let polygon = polygonPool.obtain(); - if (polygon.length != attachment.worldVerticesLength) { + if (polygon.length !== attachment.worldVerticesLength) { polygon = Utils.newFloatArray(attachment.worldVerticesLength); } polygons.push(polygon); @@ -101,13 +101,13 @@ export class SkeletonBounds { aabbCompute () { let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; - let polygons = this.polygons; + const polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) { - let polygon = polygons[i]; - let vertices = polygon; + const polygon = polygons[i]; + const vertices = polygon; for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { - let x = vertices[ii]; - let y = vertices[ii + 1]; + const x = vertices[ii]; + const y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); @@ -127,13 +127,13 @@ export class SkeletonBounds { /** Returns true if the axis aligned bounding box intersects the line segment. */ aabbIntersectsSegment (x1: number, y1: number, x2: number, y2: number) { - let minX = this.minX; - let minY = this.minY; - let maxX = this.maxX; - let maxY = this.maxY; + const minX = this.minX; + const minY = this.minY; + const maxX = this.maxX; + const maxY = this.maxY; if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) return false; - let m = (y2 - y1) / (x2 - x1); + const m = (y2 - y1) / (x2 - x1); let y = m * (minX - x1) + y1; if (y > minY && y < maxY) return true; y = m * (maxX - x1) + y1; @@ -153,7 +153,7 @@ export class SkeletonBounds { /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ containsPoint (x: number, y: number): BoundingBoxAttachment | null { - let polygons = this.polygons; + const polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) if (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i]; return null; @@ -161,16 +161,16 @@ export class SkeletonBounds { /** Returns true if the polygon contains the point. */ containsPointPolygon (polygon: NumberArrayLike, x: number, y: number) { - let vertices = polygon; - let nn = polygon.length; + const vertices = polygon; + const nn = polygon.length; let prevIndex = nn - 2; let inside = false; for (let ii = 0; ii < nn; ii += 2) { - let vertexY = vertices[ii + 1]; - let prevY = vertices[prevIndex + 1]; + const vertexY = vertices[ii + 1]; + const prevY = vertices[prevIndex + 1]; if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { - let vertexX = vertices[ii]; + const vertexX = vertices[ii]; if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside; } prevIndex = ii; @@ -182,7 +182,7 @@ export class SkeletonBounds { * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns * true. */ intersectsSegment (x1: number, y1: number, x2: number, y2: number) { - let polygons = this.polygons; + const polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i]; return null; @@ -190,20 +190,20 @@ export class SkeletonBounds { /** Returns true if the polygon contains any part of the line segment. */ intersectsSegmentPolygon (polygon: NumberArrayLike, x1: number, y1: number, x2: number, y2: number) { - let vertices = polygon; - let nn = polygon.length; + const vertices = polygon; + const nn = polygon.length; - let width12 = x1 - x2, height12 = y1 - y2; - let det1 = x1 * y2 - y1 * x2; + const width12 = x1 - x2, height12 = y1 - y2; + const det1 = x1 * y2 - y1 * x2; let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; for (let ii = 0; ii < nn; ii += 2) { - let x4 = vertices[ii], y4 = vertices[ii + 1]; - let det2 = x3 * y4 - y3 * x4; - let width34 = x3 - x4, height34 = y3 - y4; - let det3 = width12 * height34 - height12 * width34; - let x = (det1 * width34 - width12 * det2) / det3; + const x4 = vertices[ii], y4 = vertices[ii + 1]; + const det2 = x3 * y4 - y3 * x4; + const width34 = x3 - x4, height34 = y3 - y4; + const det3 = width12 * height34 - height12 * width34; + const x = (det1 * width34 - width12 * det2) / det3; if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { - let y = (det1 * height34 - height12 * det2) / det3; + const y = (det1 * height34 - height12 * det2) / det3; if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true; } x3 = x4; @@ -215,8 +215,8 @@ export class SkeletonBounds { /** Returns the polygon for the specified bounding box, or null. */ getPolygon (boundingBox: BoundingBoxAttachment) { if (!boundingBox) throw new Error("boundingBox cannot be null."); - let index = this.boundingBoxes.indexOf(boundingBox); - return index == -1 ? null : this.polygons[index]; + const index = this.boundingBoxes.indexOf(boundingBox); + return index === -1 ? null : this.polygons[index]; } /** The width of the axis aligned bounding box. */ diff --git a/spine-ts/spine-core/src/SkeletonClipping.ts b/spine-ts/spine-core/src/SkeletonClipping.ts index 267d03179..91b6dde71 100644 --- a/spine-ts/spine-core/src/SkeletonClipping.ts +++ b/spine-ts/spine-core/src/SkeletonClipping.ts @@ -27,22 +27,22 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { ClippingAttachment } from "./attachments/ClippingAttachment.js"; -import { Skeleton } from "./Skeleton.js"; -import { Slot } from "./Slot.js"; +import type { ClippingAttachment } from "./attachments/ClippingAttachment.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { Slot } from "./Slot.js"; import { Triangulator } from "./Triangulator.js"; -import { Utils, Color, NumberArrayLike } from "./Utils.js"; +import { type Color, type NumberArrayLike, Utils } from "./Utils.js"; export class SkeletonClipping { private triangulator = new Triangulator(); - private clippingPolygon = new Array(); - private clipOutput = new Array(); - clippedVertices = new Array(); + private clippingPolygon = [] as number[]; + private clipOutput = [] as number[]; + clippedVertices = [] as number[]; /** An empty array unless {@link clipTrianglesUnpacked} was used. **/ - clippedUVs = new Array(); + clippedUVs = [] as number[]; - clippedTriangles = new Array(); + clippedTriangles = [] as number[]; _clippedVerticesTyped = new Float32Array(1024); _clippedUVsTyped = new Float32Array(1024); @@ -54,7 +54,7 @@ export class SkeletonClipping { clippedUVsLength = 0; clippedTrianglesLength = 0; - private scratch = new Array(); + private scratch = [] as number[]; private clipAttachment: ClippingAttachment | null = null; private clippingPolygons: Array> | null = null; @@ -63,14 +63,14 @@ export class SkeletonClipping { if (this.clipAttachment) return 0; this.clipAttachment = clip; - let n = clip.worldVerticesLength; - let vertices = Utils.setArraySize(this.clippingPolygon, n); + const n = clip.worldVerticesLength; + const vertices = Utils.setArraySize(this.clippingPolygon, n); clip.computeWorldVertices(skeleton, slot, 0, n, vertices, 0, 2); - let clippingPolygon = this.clippingPolygon; + const clippingPolygon = this.clippingPolygon; SkeletonClipping.makeClockwise(clippingPolygon); - let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + const clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); for (let i = 0, n = clippingPolygons.length; i < n; i++) { - let polygon = clippingPolygons[i]; + const polygon = clippingPolygons[i]; SkeletonClipping.makeClockwise(polygon); polygon.push(polygon[0]); polygon.push(polygon[1]); @@ -109,10 +109,11 @@ export class SkeletonClipping { private clipTrianglesNoRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): boolean { - let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; - let clippedTriangles = this.clippedTriangles; - let polygons = this.clippingPolygons!; - let polygonsCount = polygons.length; + const clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + const clippedTriangles = this.clippedTriangles; + // biome-ignore lint/style/noNonNullAssertion: clipStart define it + const polygons = this.clippingPolygons!; + const polygonsCount = polygons.length; let index = 0; clippedVertices.length = 0; @@ -120,31 +121,31 @@ export class SkeletonClipping { let clipOutputItems = null; for (let i = 0; i < trianglesLength; i += 3) { let v = triangles[i] << 1; - let x1 = vertices[v], y1 = vertices[v + 1]; + const x1 = vertices[v], y1 = vertices[v + 1]; v = triangles[i + 1] << 1; - let x2 = vertices[v], y2 = vertices[v + 1]; + const x2 = vertices[v], y2 = vertices[v + 1]; v = triangles[i + 2] << 1; - let x3 = vertices[v], y3 = vertices[v + 1]; + const x3 = vertices[v], y3 = vertices[v + 1]; for (let p = 0; p < polygonsCount; p++) { let s = clippedVertices.length; if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { clipOutputItems = this.clipOutput; - let clipOutputLength = clipOutput.length; - if (clipOutputLength == 0) continue; + const clipOutputLength = clipOutput.length; + if (clipOutputLength === 0) continue; let clipOutputCount = clipOutputLength >> 1; - let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + const clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { - let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + const x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; clippedVerticesItems[s] = x; clippedVerticesItems[s + 1] = y; } s = clippedTriangles.length; - let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + const clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); clipOutputCount--; for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { clippedTrianglesItems[s] = index; @@ -154,7 +155,7 @@ export class SkeletonClipping { index += clipOutputCount + 1; } else { - let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + const clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); clippedVerticesItems[s] = x1; clippedVerticesItems[s + 1] = y1; @@ -165,7 +166,7 @@ export class SkeletonClipping { clippedVerticesItems[s + 5] = y3; s = clippedTriangles.length; - let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + const clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); clippedTrianglesItems[s] = index; clippedTrianglesItems[s + 1] = (index + 1); clippedTrianglesItems[s + 2] = (index + 2); @@ -180,10 +181,11 @@ export class SkeletonClipping { private clipTrianglesRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean, stride: number): boolean { - let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; - let clippedTriangles = this.clippedTriangles; - let polygons = this.clippingPolygons!; - let polygonsCount = polygons.length; + const clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + const clippedTriangles = this.clippedTriangles; + // biome-ignore lint/style/noNonNullAssertion: clipStart define it + const polygons = this.clippingPolygons!; + const polygonsCount = polygons.length; let index = 0; clippedVertices.length = 0; @@ -191,40 +193,40 @@ export class SkeletonClipping { let clipOutputItems = null; for (let i = 0; i < trianglesLength; i += 3) { let t = triangles[i]; - let u1 = uvs[t << 1], v1 = uvs[(t << 1) + 1]; - let x1 = vertices[t * stride], y1 = vertices[t * stride + 1]; + const u1 = uvs[t << 1], v1 = uvs[(t << 1) + 1]; + const x1 = vertices[t * stride], y1 = vertices[t * stride + 1]; t = triangles[i + 1]; - let u2 = uvs[t << 1], v2 = uvs[(t << 1) + 1]; - let x2 = vertices[t * stride], y2 = vertices[t * stride + 1]; + const u2 = uvs[t << 1], v2 = uvs[(t << 1) + 1]; + const x2 = vertices[t * stride], y2 = vertices[t * stride + 1]; t = triangles[i + 2]; - let u3 = uvs[t << 1], v3 = uvs[(t << 1) + 1]; - let x3 = vertices[t * stride], y3 = vertices[t * stride + 1]; + const u3 = uvs[t << 1], v3 = uvs[(t << 1) + 1]; + const x3 = vertices[t * stride], y3 = vertices[t * stride + 1]; for (let p = 0; p < polygonsCount; p++) { let s = clippedVertices.length; if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { clipOutputItems = this.clipOutput; - let clipOutputLength = clipOutput.length; - if (clipOutputLength == 0) continue; - let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; - let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + const clipOutputLength = clipOutput.length; + if (clipOutputLength === 0) continue; + const d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + const d = 1 / (d0 * d2 + d1 * (y1 - y3)); let clipOutputCount = clipOutputLength >> 1; - let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * stride); + const clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * stride); for (let ii = 0; ii < clipOutputLength; ii += 2, s += stride) { - let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + const x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; clippedVerticesItems[s] = x; clippedVerticesItems[s + 1] = y; clippedVerticesItems[s + 2] = light.r; clippedVerticesItems[s + 3] = light.g; clippedVerticesItems[s + 4] = light.b; clippedVerticesItems[s + 5] = light.a; - let c0 = x - x3, c1 = y - y3; - let a = (d0 * c0 + d1 * c1) * d; - let b = (d4 * c0 + d2 * c1) * d; - let c = 1 - a - b; + const c0 = x - x3, c1 = y - y3; + const a = (d0 * c0 + d1 * c1) * d; + const b = (d4 * c0 + d2 * c1) * d; + const c = 1 - a - b; clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; if (twoColor) { @@ -236,7 +238,7 @@ export class SkeletonClipping { } s = clippedTriangles.length; - let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + const clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); clipOutputCount--; for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { clippedTrianglesItems[s] = index; @@ -246,7 +248,7 @@ export class SkeletonClipping { index += clipOutputCount + 1; } else { - let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * stride); + const clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * stride); clippedVerticesItems[s] = x1; clippedVerticesItems[s + 1] = y1; clippedVerticesItems[s + 2] = light.r; @@ -310,7 +312,7 @@ export class SkeletonClipping { } s = clippedTriangles.length; - let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + const clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); clippedTrianglesItems[s] = index; clippedTrianglesItems[s + 1] = (index + 1); clippedTrianglesItems[s + 2] = (index + 2); @@ -325,6 +327,7 @@ export class SkeletonClipping { public clipTrianglesUnpacked (vertices: NumberArrayLike, triangles: NumberArrayLike | Uint32Array, trianglesLength: number, uvs: NumberArrayLike) { const clipOutput = this.clipOutput; let clippedVertices = this._clippedVerticesTyped, clippedUVs = this._clippedUVsTyped, clippedTriangles = this._clippedTrianglesTyped; + // biome-ignore lint/style/noNonNullAssertion: clipStart define it const polygons = this.clippingPolygons!; const polygonsCount = polygons.length; @@ -464,7 +467,7 @@ export class SkeletonClipping { /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ private clip (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array, output: Array) { - let originalOutput = output; + const originalOutput = output; let clipped = false; // Avoid copy at the end. @@ -486,20 +489,20 @@ export class SkeletonClipping { input.push(y1); output.length = 0; - let clippingVerticesLast = clippingArea.length - 4; - let clippingVertices = clippingArea; + const clippingVerticesLast = clippingArea.length - 4; + const clippingVertices = clippingArea; for (let i = 0; ; i += 2) { - let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; - let ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; + const edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + const ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; - let outputStart = output.length; - let inputVertices = input; + const outputStart = output.length; + const inputVertices = input; for (let ii = 0, nn = input.length - 2; ii < nn;) { - let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + const inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; ii += 2; - let inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; - let s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); - let s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); + const inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; + const s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); + const s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); if (s1 > 0) { if (s2) { // v1 inside, v2 inside output.push(inputX2); @@ -507,7 +510,7 @@ export class SkeletonClipping { continue; } // v1 inside, v2 outside - let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + const ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); if (t >= 0 && t <= 1) { output.push(inputX + ix * t); output.push(inputY + iy * t); @@ -517,7 +520,7 @@ export class SkeletonClipping { continue; } } else if (s2) { // v1 outside, v2 inside - let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + const ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); if (t >= 0 && t <= 1) { output.push(inputX + ix * t); output.push(inputY + iy * t); @@ -532,7 +535,7 @@ export class SkeletonClipping { clipped = true; } - if (outputStart == output.length) { // All edges outside. + if (outputStart === output.length) { // All edges outside. originalOutput.length = 0; return true; } @@ -540,14 +543,14 @@ export class SkeletonClipping { output.push(output[0]); output.push(output[1]); - if (i == clippingVerticesLast) break; - let temp = output; + if (i === clippingVerticesLast) break; + const temp = output; output = input; output.length = 0; input = temp; } - if (originalOutput != output) { + if (originalOutput !== output) { originalOutput.length = 0; for (let i = 0, n = output.length - 2; i < n; i++) originalOutput[i] = output[i]; @@ -558,8 +561,8 @@ export class SkeletonClipping { } public static makeClockwise (polygon: NumberArrayLike) { - let vertices = polygon; - let verticeslength = polygon.length; + const vertices = polygon; + const verticeslength = polygon.length; let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; for (let i = 0, n = verticeslength - 3; i < n; i += 2) { @@ -572,8 +575,8 @@ export class SkeletonClipping { if (area < 0) return; for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { - let x = vertices[i], y = vertices[i + 1]; - let other = lastX - i; + const x = vertices[i], y = vertices[i + 1]; + const other = lastX - i; vertices[i] = vertices[other]; vertices[i + 1] = vertices[other + 1]; vertices[other] = x; diff --git a/spine-ts/spine-core/src/SkeletonData.ts b/spine-ts/spine-core/src/SkeletonData.ts index 8b8649b3b..d5bfee2ea 100644 --- a/spine-ts/spine-core/src/SkeletonData.ts +++ b/spine-ts/spine-core/src/SkeletonData.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation } from "./Animation" -import { BoneData } from "./BoneData.js"; -import { ConstraintData } from "./ConstraintData"; -import { EventData } from "./EventData.js"; -import { Skin } from "./Skin.js"; -import { SlotData } from "./SlotData.js"; +import type { Animation } from "./Animation" +import type { BoneData } from "./BoneData.js"; +import type { ConstraintData } from "./ConstraintData"; +import type { EventData } from "./EventData.js"; +import type { Skin } from "./Skin.js"; +import type { SlotData } from "./SlotData.js"; /** Stores the setup pose and all of the stateless data for a skeleton. * @@ -44,12 +44,12 @@ export class SkeletonData { name: string | null = null; /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ - bones = new Array(); // Ordered parents first. + bones = [] as BoneData[]; // Ordered parents first. /** The skeleton's slots in the setup pose draw order. */ - slots = new Array(); // Setup pose draw order. + slots = [] as SlotData[]; // Setup pose draw order. - skins = new Array(); + skins = [] as Skin[]; /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. * @@ -58,13 +58,14 @@ export class SkeletonData { defaultSkin: Skin | null = null; /** The skeleton's events. */ - events = new Array(); + events = [] as EventData[]; /** The skeleton's animations. */ - animations = new Array(); + animations = [] as Animation[]; /** The skeleton's IK constraints. */ - constraints = new Array>(); + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constraints = [] as ConstraintData[]; /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ x: number = 0; @@ -103,9 +104,9 @@ export class SkeletonData { * @returns May be null. */ findBone (boneName: string) { if (!boneName) throw new Error("boneName cannot be null."); - let bones = this.bones; + const bones = this.bones; for (let i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; + if (bones[i].name === boneName) return bones[i]; return null; } @@ -114,9 +115,9 @@ export class SkeletonData { * @returns May be null. */ findSlot (slotName: string) { if (!slotName) throw new Error("slotName cannot be null."); - let slots = this.slots; + const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return slots[i]; + if (slots[i].name === slotName) return slots[i]; return null; } @@ -125,9 +126,9 @@ export class SkeletonData { * @returns May be null. */ findSkin (skinName: string) { if (!skinName) throw new Error("skinName cannot be null."); - let skins = this.skins; + const skins = this.skins; for (let i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; + if (skins[i].name === skinName) return skins[i]; return null; } @@ -136,9 +137,9 @@ export class SkeletonData { * @returns May be null. */ findEvent (eventDataName: string) { if (!eventDataName) throw new Error("eventDataName cannot be null."); - let events = this.events; + const events = this.events; for (let i = 0, n = events.length; i < n; i++) - if (events[i].name == eventDataName) return events[i]; + if (events[i].name === eventDataName) return events[i]; return null; } @@ -147,20 +148,21 @@ export class SkeletonData { * @returns May be null. */ findAnimation (animationName: string) { if (!animationName) throw new Error("animationName cannot be null."); - let animations = this.animations; + const animations = this.animations; for (let i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; + if (animations[i].name === animationName) return animations[i]; return null; } // --- Constraints. + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types findConstraint> (constraintName: string, type: new (name: string) => T): T | null { if (!constraintName) throw new Error("constraintName cannot be null."); if (type == null) throw new Error("type cannot be null."); const constraints = this.constraints; for (let i = 0, n = this.constraints.length; i < n; i++) { - let constraint = constraints[i]; + const constraint = constraints[i]; if (constraint instanceof type && constraint.name === constraintName) return constraint as T; } return null; diff --git a/spine-ts/spine-core/src/SkeletonJson.ts b/spine-ts/spine-core/src/SkeletonJson.ts index ee72f7a97..f417f58cd 100644 --- a/spine-ts/spine-core/src/SkeletonJson.ts +++ b/spine-ts/spine-core/src/SkeletonJson.ts @@ -27,25 +27,24 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, AlphaTimeline, RGBA2Timeline, RGB2Timeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline, BoneTimeline2, SliderTimeline, SliderMixTimeline } from "./Animation.js"; -import { VertexAttachment, Attachment } from "./attachments/Attachment.js"; -import { AttachmentLoader } from "./attachments/AttachmentLoader.js"; -import { MeshAttachment } from "./attachments/MeshAttachment.js"; +import { AlphaTimeline, Animation, AttachmentTimeline, type BoneTimeline2, type CurveTimeline, type CurveTimeline1, DeformTimeline, DrawOrderTimeline, EventTimeline, IkConstraintTimeline, InheritTimeline, PathConstraintMixTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintMixTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintWindTimeline, RGB2Timeline, RGBA2Timeline, RGBATimeline, RGBTimeline, RotateTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, SequenceTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, SliderMixTimeline, SliderTimeline, type Timeline, TransformConstraintTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline } from "./Animation.js"; +import type { Attachment, VertexAttachment } from "./attachments/Attachment.js"; +import type { AttachmentLoader } from "./attachments/AttachmentLoader.js"; +import type { HasTextureRegion } from "./attachments/HasTextureRegion.js"; +import type { MeshAttachment } from "./attachments/MeshAttachment.js"; +import { Sequence, SequenceMode } from "./attachments/Sequence.js"; import { BoneData, Inherit } from "./BoneData.js"; -import { EventData } from "./EventData.js"; import { Event } from "./Event.js"; +import { EventData } from "./EventData.js"; import { IkConstraintData } from "./IkConstraintData.js"; -import { PathConstraintData, PositionMode, SpacingMode, RotateMode } from "./PathConstraintData.js"; +import { PathConstraintData, PositionMode, RotateMode, SpacingMode } from "./PathConstraintData.js"; +import { PhysicsConstraintData } from "./PhysicsConstraintData.js"; import { SkeletonData } from "./SkeletonData.js"; import { Skin } from "./Skin.js"; -import { SlotData, BlendMode } from "./SlotData.js"; -import { FromProperty, FromRotate, FromScaleX, FromScaleY, FromShearY, FromX, FromY, ToProperty, ToRotate, ToScaleX, ToScaleY, ToShearY, ToX, ToY, TransformConstraintData } from "./TransformConstraintData.js"; -import { Utils, Color, NumberArrayLike } from "./Utils.js"; -import { Sequence, SequenceMode } from "./attachments/Sequence.js"; -import { SequenceTimeline } from "./Animation.js"; -import { HasTextureRegion } from "./attachments/HasTextureRegion.js"; -import { PhysicsConstraintData } from "./PhysicsConstraintData.js"; import { SliderData } from "./SliderData.js"; +import { BlendMode, SlotData } from "./SlotData.js"; +import { type FromProperty, FromRotate, FromScaleX, FromScaleY, FromShearY, FromX, FromY, type ToProperty, ToRotate, ToScaleX, ToScaleY, ToShearY, ToX, ToY, TransformConstraintData } from "./TransformConstraintData.js"; +import { Color, type NumberArrayLike, Utils } from "./Utils.js"; /** Loads skeleton data in the Spine JSON format. * @@ -60,19 +59,20 @@ export class SkeletonJson { * * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ scale = 1; - private readonly linkedMeshes = new Array(); + private readonly linkedMeshes = [] as LinkedMesh[]; constructor (attachmentLoader: AttachmentLoader) { this.attachmentLoader = attachmentLoader; } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema readSkeletonData (json: string | any): SkeletonData { - let scale = this.scale; - let skeletonData = new SkeletonData(); - let root = typeof (json) === "string" ? JSON.parse(json) : json; + const scale = this.scale; + const skeletonData = new SkeletonData(); + const root = typeof (json) === "string" ? JSON.parse(json) : json; // Skeleton - let skeletonMap = root.skeleton; + const skeletonMap = root.skeleton; if (skeletonMap) { skeletonData.hash = skeletonMap.hash; skeletonData.version = skeletonMap.spine; @@ -89,12 +89,12 @@ export class SkeletonJson { // Bones if (root.bones) { for (let i = 0; i < root.bones.length; i++) { - let boneMap = root.bones[i]; + const boneMap = root.bones[i]; let parent: BoneData | null = null; - let parentName: string = getValue(boneMap, "parent", null); + const parentName: string = getValue(boneMap, "parent", null); if (parentName) parent = skeletonData.findBone(parentName); - let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + const data = new BoneData(skeletonData.bones.length, boneMap.name, parent); data.length = getValue(boneMap, "length", 0) * scale; const setup = data.setup; setup.x = getValue(boneMap, "x", 0) * scale; @@ -107,7 +107,7 @@ export class SkeletonJson { setup.inherit = Utils.enumValue(Inherit, getValue(boneMap, "inherit", "Normal")); data.skinRequired = getValue(boneMap, "skin", false); - let color = getValue(boneMap, "color", null); + const color = getValue(boneMap, "color", null); if (color) data.color.setFromString(color); skeletonData.bones.push(data); @@ -117,17 +117,17 @@ export class SkeletonJson { // Slots. if (root.slots) { for (let i = 0; i < root.slots.length; i++) { - let slotMap = root.slots[i]; - let slotName = slotMap.name; + const slotMap = root.slots[i]; + const slotName = slotMap.name; - let boneData = skeletonData.findBone(slotMap.bone); + const boneData = skeletonData.findBone(slotMap.bone); if (!boneData) throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`); - let data = new SlotData(skeletonData.slots.length, slotName, boneData); + const data = new SlotData(skeletonData.slots.length, slotName, boneData); - let color: string = getValue(slotMap, "color", null); + const color: string = getValue(slotMap, "color", null); if (color) data.setup.color.setFromString(color); - let dark: string = getValue(slotMap, "dark", null); + const dark: string = getValue(slotMap, "dark", null); if (dark) data.setup.darkColor = Color.fromString(dark); data.attachmentName = getValue(slotMap, "attachment", null); @@ -148,7 +148,7 @@ export class SkeletonJson { data.skinRequired = skinRequired; for (let ii = 0; ii < constraintMap.bones.length; ii++) { - let bone = skeletonData.findBone(constraintMap.bones[ii]); + const bone = skeletonData.findBone(constraintMap.bones[ii]); if (!bone) throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${name}.`); data.bones.push(bone); } @@ -174,8 +174,8 @@ export class SkeletonJson { data.skinRequired = skinRequired; for (let ii = 0; ii < constraintMap.bones.length; ii++) { - let boneName = constraintMap.bones[ii]; - let bone = skeletonData.findBone(boneName); + const boneName = constraintMap.bones[ii]; + const bone = skeletonData.findBone(boneName); if (!bone) throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); data.bones.push(bone); } @@ -191,12 +191,12 @@ export class SkeletonJson { data.clamp = getValue(constraintMap, "clamp", false); let rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false; - const fromEntries = Object.entries(getValue(constraintMap, "properties", {})) as [string, any][]; + const fromEntries = Object.entries(getValue(constraintMap, "properties", {})) as [string, object][]; for (const [name, fromEntry] of fromEntries) { const from = this.fromProperty(name); const fromScale = this.propertyScale(name, scale); from.offset = getValue(fromEntry, "offset", 0) * fromScale; - const toEntries = Object.entries(getValue(fromEntry, "to", {})) as [string, any][]; + const toEntries = Object.entries(getValue(fromEntry, "to", {})) as [string, object][]; for (const [name, toEntry] of toEntries) { let toScale = 1; let to: ToProperty; @@ -233,7 +233,7 @@ export class SkeletonJson { to = new ToShearY(); break; } - default: throw new Error("Invalid transform constraint to property: " + name); + default: throw new Error(`Invalid transform constraint to property: ${name}`); } to.offset = getValue(toEntry, "offset", 0) * toScale; to.max = getValue(toEntry, "max", 1) * toScale; @@ -266,8 +266,8 @@ export class SkeletonJson { data.skinRequired = skinRequired; for (let ii = 0; ii < constraintMap.bones.length; ii++) { - let boneName = constraintMap.bones[ii]; - let bone = skeletonData.findBone(boneName); + const boneName = constraintMap.bones[ii]; + const bone = skeletonData.findBone(boneName); if (!bone) throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); data.bones.push(bone); } @@ -283,9 +283,9 @@ export class SkeletonJson { data.offsetRotation = getValue(constraintMap, "rotation", 0); const setup = data.setup; setup.position = getValue(constraintMap, "position", 0); - if (data.positionMode == PositionMode.Fixed) setup.position *= scale; + if (data.positionMode === PositionMode.Fixed) setup.position *= scale; setup.spacing = getValue(constraintMap, "spacing", 0); - if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) setup.spacing *= scale; + if (data.spacingMode === SpacingMode.Length || data.spacingMode === SpacingMode.Fixed) setup.spacing *= scale; setup.mixRotate = getValue(constraintMap, "mixRotate", 1); setup.mixX = getValue(constraintMap, "mixX", 1); setup.mixY = getValue(constraintMap, "mixY", setup.mixX); @@ -299,7 +299,7 @@ export class SkeletonJson { const boneName: string = constraintMap.bone; const bone = skeletonData.findBone(boneName); - if (bone == null) throw new Error("Physics bone not found: " + boneName); + if (bone == null) throw new Error(`Physics bone not found: ${boneName}`); data.bone = bone; data.x = getValue(constraintMap, "x", 0); @@ -340,7 +340,7 @@ export class SkeletonJson { const boneName: string = constraintMap.bone; if (boneName) { data.bone = skeletonData.findBone(boneName); - if (!data.bone) throw new Error("Slider bone not found: " + boneName); + if (!data.bone) throw new Error(`Slider bone not found: ${boneName}`); const property = constraintMap.property; data.property = this.fromProperty(property); const propertyScale = this.propertyScale(property, scale); @@ -360,13 +360,13 @@ export class SkeletonJson { // Skins. if (root.skins) { for (let i = 0; i < root.skins.length; i++) { - let skinMap = root.skins[i] - let skin = new Skin(skinMap.name); + const skinMap = root.skins[i] + const skin = new Skin(skinMap.name); if (skinMap.bones) { for (let ii = 0; ii < skinMap.bones.length; ii++) { - let boneName = skinMap.bones[ii]; - let bone = skeletonData.findBone(boneName); + const boneName = skinMap.bones[ii]; + const bone = skeletonData.findBone(boneName); if (!bone) throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); skin.bones.push(bone); } @@ -374,8 +374,8 @@ export class SkeletonJson { if (skinMap.ik) { for (let ii = 0; ii < skinMap.ik.length; ii++) { - let constraintName = skinMap.ik[ii]; - let constraint = skeletonData.findConstraint(constraintName, IkConstraintData); + const constraintName = skinMap.ik[ii]; + const constraint = skeletonData.findConstraint(constraintName, IkConstraintData); if (!constraint) throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); skin.constraints.push(constraint); } @@ -383,8 +383,8 @@ export class SkeletonJson { if (skinMap.transform) { for (let ii = 0; ii < skinMap.transform.length; ii++) { - let constraintName = skinMap.transform[ii]; - let constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); + const constraintName = skinMap.transform[ii]; + const constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); if (!constraint) throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); skin.constraints.push(constraint); } @@ -392,8 +392,8 @@ export class SkeletonJson { if (skinMap.path) { for (let ii = 0; ii < skinMap.path.length; ii++) { - let constraintName = skinMap.path[ii]; - let constraint = skeletonData.findConstraint(constraintName, PathConstraintData); + const constraintName = skinMap.path[ii]; + const constraint = skeletonData.findConstraint(constraintName, PathConstraintData); if (!constraint) throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); skin.constraints.push(constraint); } @@ -401,8 +401,8 @@ export class SkeletonJson { if (skinMap.physics) { for (let ii = 0; ii < skinMap.physics.length; ii++) { - let constraintName = skinMap.physics[ii]; - let constraint = skeletonData.findConstraint(constraintName, PhysicsConstraintData); + const constraintName = skinMap.physics[ii]; + const constraint = skeletonData.findConstraint(constraintName, PhysicsConstraintData); if (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); skin.constraints.push(constraint); } @@ -410,33 +410,33 @@ export class SkeletonJson { if (skinMap.slider) { for (let ii = 0; ii < skinMap.slider.length; ii++) { - let constraintName = skinMap.slider[ii]; - let constraint = skeletonData.findConstraint(constraintName, SliderData); + const constraintName = skinMap.slider[ii]; + const constraint = skeletonData.findConstraint(constraintName, SliderData); if (!constraint) throw new Error(`Couldn't find slider constraint ${constraintName} for skin ${skinMap.name}.`); skin.constraints.push(constraint); } } - for (let slotName in skinMap.attachments) { - let slot = skeletonData.findSlot(slotName); + for (const slotName in skinMap.attachments) { + const slot = skeletonData.findSlot(slotName); if (!slot) throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); - let slotMap = skinMap.attachments[slotName]; - for (let entryName in slotMap) { - let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + const slotMap = skinMap.attachments[slotName]; + for (const entryName in slotMap) { + const attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); if (attachment) skin.setAttachment(slot.index, entryName, attachment); } } skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; + if (skin.name === "default") skeletonData.defaultSkin = skin; } } // Linked meshes. for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { - let linkedMesh = this.linkedMeshes[i]; - let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + const linkedMesh = this.linkedMeshes[i]; + const skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); if (!skin) throw new Error(`Skin not found: ${linkedMesh.skin}`); - let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + const parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); if (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; linkedMesh.mesh.setParentMesh(parent); @@ -446,9 +446,9 @@ export class SkeletonJson { // Events. if (root.events) { - for (let eventName in root.events) { - let eventMap = root.events[eventName]; - let data = new EventData(eventName); + for (const eventName in root.events) { + const eventMap = root.events[eventName]; + const data = new EventData(eventName); data.intValue = getValue(eventMap, "int", 0); data.floatValue = getValue(eventMap, "float", 0); data.stringValue = getValue(eventMap, "string", ""); @@ -463,22 +463,23 @@ export class SkeletonJson { // Animations. if (root.animations) { - for (let animationName in root.animations) { - let animationMap = root.animations[animationName]; + for (const animationName in root.animations) { + const animationMap = root.animations[animationName]; this.readAnimation(animationMap, animationName, skeletonData); } } // Slider animations. if (root.constraints) { - for (let animationName in root.constraints) { - let animationMap = root.constraints[animationName]; + for (const animationName in root.constraints) { + const animationMap = root.constraints[animationName]; if (animationMap.type === "slider") { - const data = skeletonData.findConstraint(animationMap.name, SliderData)!; + const data = skeletonData.findConstraint(animationMap.name, SliderData) const animationName = animationMap.animation; const animation = skeletonData.findAnimation(animationName); - if (!animation) throw new Error("Slider animation not found: " + animationName); - data.animation = animation; + if (!animation) throw new Error(`Slider animation not found: ${animationName}`); + // biome-ignore lint/style/noNonNullAssertion: reference runtime + data!.animation = animation; } } } @@ -495,7 +496,7 @@ export class SkeletonJson { case "scaleX": from = new FromScaleX(); break; case "scaleY": from = new FromScaleY(); break; case "shearY": from = new FromShearY(); break; - default: throw new Error("Invalid transform constraint from property: " + type); + default: throw new Error(`Invalid transform constraint from property: ${type}`); } return from; } @@ -505,18 +506,19 @@ export class SkeletonJson { case "x": case "y": return scale; default: return 1; - }; + } } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema readAttachment (map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment | null { - let scale = this.scale; + const scale = this.scale; name = getValue(map, "name", name); switch (getValue(map, "type", "region")) { case "region": { - let path = getValue(map, "path", name); - let sequence = this.readSequence(getValue(map, "sequence", null)); - let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + const path = getValue(map, "path", name); + const sequence = this.readSequence(getValue(map, "sequence", null)); + const region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); if (!region) return null; region.path = path; region.x = getValue(map, "x", 0) * scale; @@ -528,42 +530,42 @@ export class SkeletonJson { region.height = map.height * scale; region.sequence = sequence; - let color: string = getValue(map, "color", null); + const color: string = getValue(map, "color", null); if (color) region.color.setFromString(color); if (region.region != null) region.updateRegion(); return region; } case "boundingbox": { - let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + const box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); if (!box) return null; this.readVertices(map, box, map.vertexCount << 1); - let color: string = getValue(map, "color", null); + const color: string = getValue(map, "color", null); if (color) box.color.setFromString(color); return box; } case "mesh": case "linkedmesh": { - let path = getValue(map, "path", name); - let sequence = this.readSequence(getValue(map, "sequence", null)); - let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + const path = getValue(map, "path", name); + const sequence = this.readSequence(getValue(map, "sequence", null)); + const mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); if (!mesh) return null; mesh.path = path; - let color = getValue(map, "color", null); + const color = getValue(map, "color", null); if (color) mesh.color.setFromString(color); mesh.width = getValue(map, "width", 0) * scale; mesh.height = getValue(map, "height", 0) * scale; mesh.sequence = sequence; - let parent: string = getValue(map, "parent", null); + const parent: string = getValue(map, "parent", null); if (parent) { this.linkedMeshes.push(new LinkedMesh(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true))); return mesh; } - let uvs: Array = map.uvs; + const uvs: Array = map.uvs; this.readVertices(map, mesh, uvs.length); mesh.triangles = map.triangles; mesh.regionUVs = uvs; @@ -574,45 +576,45 @@ export class SkeletonJson { return mesh; } case "path": { - let path = this.attachmentLoader.newPathAttachment(skin, name); + const path = this.attachmentLoader.newPathAttachment(skin, name); if (!path) return null; path.closed = getValue(map, "closed", false); path.constantSpeed = getValue(map, "constantSpeed", true); - let vertexCount = map.vertexCount; + const vertexCount = map.vertexCount; this.readVertices(map, path, vertexCount << 1); - let lengths: Array = Utils.newArray(vertexCount / 3, 0); + const lengths: Array = Utils.newArray(vertexCount / 3, 0); for (let i = 0; i < map.lengths.length; i++) lengths[i] = map.lengths[i] * scale; path.lengths = lengths; - let color: string = getValue(map, "color", null); + const color: string = getValue(map, "color", null); if (color) path.color.setFromString(color); return path; } case "point": { - let point = this.attachmentLoader.newPointAttachment(skin, name); + const point = this.attachmentLoader.newPointAttachment(skin, name); if (!point) return null; point.x = getValue(map, "x", 0) * scale; point.y = getValue(map, "y", 0) * scale; point.rotation = getValue(map, "rotation", 0); - let color = getValue(map, "color", null); + const color = getValue(map, "color", null); if (color) point.color.setFromString(color); return point; } case "clipping": { - let clip = this.attachmentLoader.newClippingAttachment(skin, name); + const clip = this.attachmentLoader.newClippingAttachment(skin, name); if (!clip) return null; - let end = getValue(map, "end", null); + const end = getValue(map, "end", null); if (end) clip.endSlot = skeletonData.findSlot(end); - let vertexCount = map.vertexCount; + const vertexCount = map.vertexCount; this.readVertices(map, clip, vertexCount << 1); - let color: string = getValue(map, "color", null); + const color: string = getValue(map, "color", null); if (color) clip.color.setFromString(color); return clip; } @@ -620,32 +622,33 @@ export class SkeletonJson { return null; } - readSequence (map: any) { + readSequence (map: object) { if (map == null) return null; - let sequence = new Sequence(getValue(map, "count", 0)); + const sequence = new Sequence(getValue(map, "count", 0)); sequence.start = getValue(map, "start", 1); sequence.digits = getValue(map, "digits", 0); sequence.setupIndex = getValue(map, "setup", 0); return sequence; } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema readVertices (map: any, attachment: VertexAttachment, verticesLength: number) { - let scale = this.scale; + const scale = this.scale; attachment.worldVerticesLength = verticesLength; - let vertices: Array = map.vertices; - if (verticesLength == vertices.length) { - let scaledVertices = Utils.toFloatArray(vertices); - if (scale != 1) { + const vertices: Array = map.vertices; + if (verticesLength === vertices.length) { + const scaledVertices = Utils.toFloatArray(vertices); + if (scale !== 1) { for (let i = 0, n = vertices.length; i < n; i++) scaledVertices[i] *= scale; } attachment.vertices = scaledVertices; return; } - let weights = new Array(); - let bones = new Array(); + const weights: number[] = []; + const bones: number[] = []; for (let i = 0, n = vertices.length; i < n;) { - let boneCount = vertices[i++]; + const boneCount = vertices[i++]; bones.push(boneCount); for (let nn = i + boneCount * 4; i < nn; i += 4) { bones.push(vertices[i]); @@ -658,48 +661,49 @@ export class SkeletonJson { attachment.vertices = Utils.toFloatArray(weights); } + // biome-ignore lint/suspicious/noExplicitAny: it is any untile we define a schema readAnimation (map: any, name: string, skeletonData: SkeletonData) { - let scale = this.scale; - let timelines = new Array(); + const scale = this.scale; + const timelines: Timeline[] = []; // Slot timelines. if (map.slots) { - for (let slotName in map.slots) { - let slotMap = map.slots[slotName]; - let slot = skeletonData.findSlot(slotName); - if (!slot) throw new Error("Slot not found: " + slotName); - let slotIndex = slot.index; - for (let timelineName in slotMap) { - let timelineMap = slotMap[timelineName]; + for (const slotName in map.slots) { + const slotMap = map.slots[slotName]; + const slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error(`Slot not found: ${slotName}`); + const slotIndex = slot.index; + for (const timelineName in slotMap) { + const timelineMap = slotMap[timelineName]; if (!timelineMap) continue; - let frames = timelineMap.length; + const frames = timelineMap.length; switch (timelineName) { case "attachment": { - let timeline = new AttachmentTimeline(frames, slotIndex); + const timeline = new AttachmentTimeline(frames, slotIndex); for (let frame = 0; frame < frames; frame++) { - let keyMap = timelineMap[frame]; + const keyMap = timelineMap[frame]; timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); } timelines.push(timeline); break; } case "rgba": { - let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + const timeline = new RGBATimeline(frames, frames << 2, slotIndex); let keyMap = timelineMap[0]; let time = getValue(keyMap, "time", 0); let color = Color.fromString(keyMap.color); for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let newColor = Color.fromString(nextMap.color); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.color); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); @@ -715,21 +719,21 @@ export class SkeletonJson { break; } case "rgb": { - let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + const timeline = new RGBTimeline(frames, frames * 3, slotIndex); let keyMap = timelineMap[0]; let time = getValue(keyMap, "time", 0); let color = Color.fromString(keyMap.color); for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, color.r, color.g, color.b); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let newColor = Color.fromString(nextMap.color); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.color); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); @@ -748,7 +752,7 @@ export class SkeletonJson { break; } case "rgba2": { - let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + const timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); let keyMap = timelineMap[0]; let time = getValue(keyMap, "time", 0); @@ -757,15 +761,15 @@ export class SkeletonJson { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let newColor = Color.fromString(nextMap.light); - let newColor2 = Color.fromString(nextMap.dark); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.light); + const newColor2 = Color.fromString(nextMap.dark); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); @@ -785,7 +789,7 @@ export class SkeletonJson { break; } case "rgb2": { - let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + const timeline = new RGB2Timeline(frames, frames * 6, slotIndex); let keyMap = timelineMap[0]; let time = getValue(keyMap, "time", 0); @@ -794,15 +798,15 @@ export class SkeletonJson { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let newColor = Color.fromString(nextMap.light); - let newColor2 = Color.fromString(nextMap.dark); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.light); + const newColor2 = Color.fromString(nextMap.dark); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); @@ -821,7 +825,7 @@ export class SkeletonJson { break; } default: - throw new Error("Invalid timeline type for a slot: " + timelineMap.name + " (" + slotMap.name + ")"); + throw new Error(`Invalid timeline type for a slot: ${timelineMap.name} (${slotMap.name})`); } } } @@ -829,15 +833,15 @@ export class SkeletonJson { // Bone timelines. if (map.bones) { - for (let boneName in map.bones) { - let boneMap = map.bones[boneName]; - let bone = skeletonData.findBone(boneName); - if (!bone) throw new Error("Bone not found: " + boneName); - let boneIndex = bone.index; - for (let timelineName in boneMap) { - let timelineMap = boneMap[timelineName]; - let frames = timelineMap.length; - if (frames == 0) continue; + for (const boneName in map.bones) { + const boneMap = map.bones[boneName]; + const bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Bone not found: ${boneName}`); + const boneIndex = bone.index; + for (const timelineName in boneMap) { + const timelineMap = boneMap[timelineName]; + const frames = timelineMap.length; + if (frames === 0) continue; switch (timelineName) { case "rotate": readTimeline1(timelines, timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1); break; @@ -850,16 +854,17 @@ export class SkeletonJson { case "shear": readTimeline2(timelines, timelineMap, new ShearTimeline(frames, frames << 1, boneIndex), "x", "y", 0, 1); break; case "shearx": readTimeline1(timelines, timelineMap, new ShearXTimeline(frames, frames, boneIndex), 0, 1); break; case "sheary": readTimeline1(timelines, timelineMap, new ShearYTimeline(frames, frames, boneIndex), 0, 1); break; - case "inherit": + case "inherit": { const timeline = new InheritTimeline(frames, bone.index); for (let frame = 0; frame < timelineMap.length; frame++) { - let aFrame = timelineMap[frame]; + const aFrame = timelineMap[frame]; timeline.setFrame(frame, getValue(aFrame, "time", 0), Utils.enumValue(Inherit, getValue(aFrame, "inherit", "Normal"))); } timelines.push(timeline); break; + } default: - throw new Error("Invalid timeline type for a bone: " + timelineMap.name + " (" + boneMap.name + ")"); + throw new Error(`Invalid timeline type for a bone: ${timelineMap.name} (${boneMap.name})`); } } @@ -868,13 +873,13 @@ export class SkeletonJson { // IK constraint timelines. if (map.ik) { - for (let constraintName in map.ik) { - let constraintMap = map.ik[constraintName]; + for (const constraintName in map.ik) { + const constraintMap = map.ik[constraintName]; let keyMap = constraintMap[0]; if (!keyMap) continue; - let constraint = skeletonData.findConstraint(constraintName, IkConstraintData); - if (!constraint) throw new Error("IK Constraint not found: " + constraintName); + const constraint = skeletonData.findConstraint(constraintName, IkConstraintData); + if (!constraint) throw new Error(`IK Constraint not found: ${constraintName}`); const timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, skeletonData.constraints.indexOf(constraint)); @@ -884,16 +889,16 @@ export class SkeletonJson { for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); - let nextMap = constraintMap[frame + 1]; + const nextMap = constraintMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let mix2 = getValue(nextMap, "mix", 1); - let softness2 = getValue(nextMap, "softness", 0) * scale; - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const mix2 = getValue(nextMap, "mix", 1); + const softness2 = getValue(nextMap, "softness", 0) * scale; + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); @@ -910,36 +915,36 @@ export class SkeletonJson { // Transform constraint timelines. if (map.transform) { - for (let constraintName in map.transform) { - let timelineMap = map.transform[constraintName]; + for (const constraintName in map.transform) { + const timelineMap = map.transform[constraintName]; let keyMap = timelineMap[0]; if (!keyMap) continue; - let constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); - if (!constraint) throw new Error("Transform constraint not found: " + constraintName); - let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, + const constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); + if (!constraint) throw new Error(`Transform constraint not found: ${constraintName}`); + const timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, skeletonData.constraints.indexOf(constraint)); let time = getValue(keyMap, "time", 0); let mixRotate = getValue(keyMap, "mixRotate", 1); let mixX = getValue(keyMap, "mixX", 1), mixY = getValue(keyMap, "mixY", mixX); let mixScaleX = getValue(keyMap, "mixScaleX", 1), mixScaleY = getValue(keyMap, "mixScaleY", 1); - let mixShearY = getValue(keyMap, "mixShearY", 1); + const mixShearY = getValue(keyMap, "mixShearY", 1); for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let mixRotate2 = getValue(nextMap, "mixRotate", 1); - let mixX2 = getValue(nextMap, "mixX", 1), mixY2 = getValue(nextMap, "mixY", mixX2); - let mixScaleX2 = getValue(nextMap, "mixScaleX", 1), mixScaleY2 = getValue(nextMap, "mixScaleY", 1); - let mixShearY2 = getValue(nextMap, "mixShearY", 1); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const mixRotate2 = getValue(nextMap, "mixRotate", 1); + const mixX2 = getValue(nextMap, "mixX", 1), mixY2 = getValue(nextMap, "mixY", mixX2); + const mixScaleX2 = getValue(nextMap, "mixScaleX", 1), mixScaleY2 = getValue(nextMap, "mixScaleY", 1); + const mixShearY2 = getValue(nextMap, "mixShearY", 1); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); @@ -964,10 +969,10 @@ export class SkeletonJson { // Path constraint timelines. if (map.path) { - for (let constraintName in map.path) { + for (const constraintName in map.path) { const constraintMap = map.path[constraintName]; const constraint = skeletonData.findConstraint(constraintName, PathConstraintData); - if (!constraint) throw new Error("Path constraint not found: " + constraintName); + if (!constraint) throw new Error(`Path constraint not found: ${constraintName}`); const index = skeletonData.constraints.indexOf(constraint); for (const timelineName in constraintMap) { const timelineMap = constraintMap[timelineName]; @@ -978,12 +983,12 @@ export class SkeletonJson { switch (timelineName) { case "position": { const timeline = new PathConstraintPositionTimeline(frames, frames, index); - readTimeline1(timelines, timelineMap, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1); + readTimeline1(timelines, timelineMap, timeline, 0, constraint.positionMode === PositionMode.Fixed ? scale : 1); break; } case "spacing": { const timeline = new PathConstraintSpacingTimeline(frames, frames, index); - readTimeline1(timelines, timelineMap, timeline, 0, constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1); + readTimeline1(timelines, timelineMap, timeline, 0, constraint.spacingMode === SpacingMode.Length || constraint.spacingMode === SpacingMode.Fixed ? scale : 1); break; } case "mix": { @@ -994,16 +999,16 @@ export class SkeletonJson { let mixY = getValue(keyMap, "mixY", mixX); for (let frame = 0, bezier = 0; ; frame++) { timeline.setFrame(frame, time, mixRotate, mixX, mixY); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let mixRotate2 = getValue(nextMap, "mixRotate", 1); - let mixX2 = getValue(nextMap, "mixX", 1); - let mixY2 = getValue(nextMap, "mixY", mixX2); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const mixRotate2 = getValue(nextMap, "mixRotate", 1); + const mixX2 = getValue(nextMap, "mixX", 1); + const mixY2 = getValue(nextMap, "mixY", mixX2); + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); @@ -1030,7 +1035,7 @@ export class SkeletonJson { let index = -1; if (constraintName.length > 0) { const constraint = skeletonData.findConstraint(constraintName, PhysicsConstraintData); - if (!constraint) throw new Error("Physics constraint not found: " + constraintName); + if (!constraint) throw new Error(`Physics constraint not found: ${constraintName}`); index = skeletonData.constraints.indexOf(constraint); } for (const timelineName in constraintMap) { @@ -1039,7 +1044,7 @@ export class SkeletonJson { if (!keyMap) continue; const frames = timelineMap.length; - let timeline; + let timeline: CurveTimeline1; let defaultValue = 0; if (timelineName === "reset") { const resetTimeline = new PhysicsConstraintResetTimeline(frames, index); @@ -1055,10 +1060,14 @@ export class SkeletonJson { case "mass": timeline = new PhysicsConstraintMassTimeline(frames, frames, index); break; case "wind": timeline = new PhysicsConstraintWindTimeline(frames, frames, index); break; case "gravity": timeline = new PhysicsConstraintGravityTimeline(frames, frames, index); break; - case "mix": timeline = new PhysicsConstraintMixTimeline(frames, frames, index); break; + case "mix": { + defaultValue = 1; + timeline = new PhysicsConstraintMixTimeline(frames, frames, index); + break; + } default: continue; } - readTimeline1(timelines, timelineMap, timeline, 0, 1); + readTimeline1(timelines, timelineMap, timeline, defaultValue, 1); } } } @@ -1068,12 +1077,12 @@ export class SkeletonJson { for (const constraintName in map.slider) { const constraintMap = map.slider[constraintName]; const constraint = skeletonData.findConstraint(constraintName, SliderData); - if (!constraint) throw new Error("Slider not found: " + constraintName); + if (!constraint) throw new Error(`Slider not found: ${constraintName}`); const index = skeletonData.constraints.indexOf(constraint); for (const timelineName in constraintMap) { const timelineMap = constraintMap[timelineName]; - let keyMap = timelineMap[0]; + const keyMap = timelineMap[0]; if (!keyMap) continue; const frames = timelineMap.length; @@ -1087,42 +1096,42 @@ export class SkeletonJson { // Attachment timelines. if (map.attachments) { - for (let attachmentsName in map.attachments) { - let attachmentsMap = map.attachments[attachmentsName]; - let skin = skeletonData.findSkin(attachmentsName); - if (!skin) throw new Error("Skin not found: " + attachmentsName); - for (let slotMapName in attachmentsMap) { - let slotMap = attachmentsMap[slotMapName]; - let slot = skeletonData.findSlot(slotMapName); - if (!slot) throw new Error("Slot not found: " + slotMapName); - let slotIndex = slot.index; - for (let attachmentMapName in slotMap) { - let attachmentMap = slotMap[attachmentMapName]; - let attachment = skin.getAttachment(slotIndex, attachmentMapName); - if (!attachment) throw new Error("Timeline attachment not found: " + attachmentMapName); + for (const attachmentsName in map.attachments) { + const attachmentsMap = map.attachments[attachmentsName]; + const skin = skeletonData.findSkin(attachmentsName); + if (!skin) throw new Error(`Skin not found: ${attachmentsName}`); + for (const slotMapName in attachmentsMap) { + const slotMap = attachmentsMap[slotMapName]; + const slot = skeletonData.findSlot(slotMapName); + if (!slot) throw new Error(`Slot not found: ${slotMapName}`); + const slotIndex = slot.index; + for (const attachmentMapName in slotMap) { + const attachmentMap = slotMap[attachmentMapName]; + const attachment = skin.getAttachment(slotIndex, attachmentMapName); + if (!attachment) throw new Error(`Timeline attachment not found: ${attachmentMapName}`); - for (let timelineMapName in attachmentMap) { - let timelineMap = attachmentMap[timelineMapName]; + for (const timelineMapName in attachmentMap) { + const timelineMap = attachmentMap[timelineMapName]; let keyMap = timelineMap[0]; if (!keyMap) continue; - if (timelineMapName == "deform") { - let weighted = attachment.bones; - let vertices = attachment.vertices; - let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + if (timelineMapName === "deform") { + const weighted = attachment.bones; + const vertices = attachment.vertices; + const deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; - let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + const timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); let time = getValue(keyMap, "time", 0); for (let frame = 0, bezier = 0; ; frame++) { let deform: NumberArrayLike; - let verticesValue: Array = getValue(keyMap, "vertices", null); + const verticesValue: Array = getValue(keyMap, "vertices", null); if (!verticesValue) deform = weighted ? Utils.newFloatArray(deformLength) : vertices; else { deform = Utils.newFloatArray(deformLength); - let start = getValue(keyMap, "offset", 0); + const start = getValue(keyMap, "offset", 0); Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); - if (scale != 1) { + if (scale !== 1) { for (let i = start, n = i + verticesValue.length; i < n; i++) deform[i] *= scale; } @@ -1133,26 +1142,26 @@ export class SkeletonJson { } timeline.setFrame(frame, time, deform); - let nextMap = timelineMap[frame + 1]; + const nextMap = timelineMap[frame + 1]; if (!nextMap) { timeline.shrink(bezier); break; } - let time2 = getValue(nextMap, "time", 0); - let curve = keyMap.curve; + const time2 = getValue(nextMap, "time", 0); + const curve = keyMap.curve; if (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); time = time2; keyMap = nextMap; } timelines.push(timeline); - } else if (timelineMapName == "sequence") { - let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment as unknown as HasTextureRegion); + } else if (timelineMapName === "sequence") { + const timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment as unknown as HasTextureRegion); let lastDelay = 0; for (let frame = 0; frame < timelineMap.length; frame++) { - let delay = getValue(keyMap, "delay", lastDelay); - let time = getValue(keyMap, "time", 0); - let mode = SequenceMode[getValue(keyMap, "mode", "hold")] as unknown as number; - let index = getValue(keyMap, "index", 0); + const delay = getValue(keyMap, "delay", lastDelay); + const time = getValue(keyMap, "time", 0); + const mode = SequenceMode[getValue(keyMap, "mode", "hold")] as unknown as number; + const index = getValue(keyMap, "index", 0); timeline.setFrame(frame, time, mode, index, delay); lastDelay = delay; keyMap = timelineMap[frame + 1]; @@ -1167,24 +1176,24 @@ export class SkeletonJson { // Draw order timelines. if (map.drawOrder) { - let timeline = new DrawOrderTimeline(map.drawOrder.length); - let slotCount = skeletonData.slots.length; + const timeline = new DrawOrderTimeline(map.drawOrder.length); + const slotCount = skeletonData.slots.length; let frame = 0; for (let i = 0; i < map.drawOrder.length; i++, frame++) { - let drawOrderMap = map.drawOrder[i]; + const drawOrderMap = map.drawOrder[i]; let drawOrder: Array | null = null; - let offsets = getValue(drawOrderMap, "offsets", null); + const offsets = getValue(drawOrderMap, "offsets", null); if (offsets) { drawOrder = Utils.newArray(slotCount, -1); - let unchanged = Utils.newArray(slotCount - offsets.length, 0); + const unchanged = Utils.newArray(slotCount - offsets.length, 0); let originalIndex = 0, unchangedIndex = 0; for (let ii = 0; ii < offsets.length; ii++) { - let offsetMap = offsets[ii]; - let slot = skeletonData.findSlot(offsetMap.slot); - if (!slot) throw new Error("Slot not found: " + slot); - let slotIndex = slot.index; + const offsetMap = offsets[ii]; + const slot = skeletonData.findSlot(offsetMap.slot); + if (!slot) throw new Error(`Slot not found: ${slot}`); + const slotIndex = slot.index; // Collect unchanged items. - while (originalIndex != slotIndex) + while (originalIndex !== slotIndex) unchanged[unchangedIndex++] = originalIndex++; // Set changed items. drawOrder[originalIndex + offsetMap.offset] = originalIndex++; @@ -1194,7 +1203,7 @@ export class SkeletonJson { unchanged[unchangedIndex++] = originalIndex++; // Fill in unchanged items. for (let ii = slotCount - 1; ii >= 0; ii--) - if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + if (drawOrder[ii] === -1) drawOrder[ii] = unchanged[--unchangedIndex]; } timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); } @@ -1203,13 +1212,13 @@ export class SkeletonJson { // Event timelines. if (map.events) { - let timeline = new EventTimeline(map.events.length); + const timeline = new EventTimeline(map.events.length); let frame = 0; for (let i = 0; i < map.events.length; i++, frame++) { - let eventMap = map.events[i]; - let eventData = skeletonData.findEvent(eventMap.name); - if (!eventData) throw new Error("Event not found: " + eventMap.name); - let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + const eventMap = map.events[i]; + const eventData = skeletonData.findEvent(eventMap.name); + if (!eventData) throw new Error(`Event not found: ${eventMap.name}`); + const event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); event.intValue = getValue(eventMap, "int", eventData.intValue); event.floatValue = getValue(eventMap, "float", eventData.floatValue); event.stringValue = getValue(eventMap, "string", eventData.stringValue); @@ -1244,21 +1253,26 @@ class LinkedMesh { } } -function readTimeline1 (timelines: Array, keys: any[], timeline: CurveTimeline1, defaultValue: number, scale: number) { +type CurveType = [number, number, number, number] | "stepped"; +type Timeline1KeysType = { value: number, time?: number, curve?: CurveType }; +type Timeline2KeysType = Timeline1KeysType & { x?: number, y?: number }; + +function readTimeline1 (timelines: Array, keys: Timeline1KeysType[], timeline: CurveTimeline1, defaultValue: number, scale: number) { let keyMap = keys[0]; - let time = getValue(keyMap, "time", 0); - let value = getValue(keyMap, "value", defaultValue) * scale; + let time = keyMap.time ?? 0; + let value = (keyMap.value ?? defaultValue) * scale; let bezier = 0; + for (let frame = 0; ; frame++) { timeline.setFrame(frame, time, value); - let nextMap = keys[frame + 1]; + const nextMap = keys[frame + 1]; if (!nextMap) { timeline.shrink(bezier); timelines.push(timeline); return; } - let time2 = getValue(nextMap, "time", 0); - let value2 = getValue(nextMap, "value", defaultValue) * scale; + const time2 = nextMap.time ?? 0; + const value2 = (nextMap.value ?? defaultValue) * scale; if (keyMap.curve) bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); time = time2; value = value2; @@ -1266,24 +1280,24 @@ function readTimeline1 (timelines: Array, keys: any[], timeline: Curve } } -function readTimeline2 (timelines: Array, keys: any[], timeline: BoneTimeline2, name1: string, name2: string, defaultValue: number, scale: number) { +function readTimeline2 (timelines: Array, keys: Timeline2KeysType[], timeline: BoneTimeline2, name1: "x", name2: "y", defaultValue: number, scale: number) { let keyMap = keys[0]; - let time = getValue(keyMap, "time", 0); - let value1 = getValue(keyMap, name1, defaultValue) * scale; - let value2 = getValue(keyMap, name2, defaultValue) * scale; + let time = keyMap.time ?? 0; + let value1 = (keyMap[name1] ?? defaultValue) * scale; + let value2 = (keyMap[name2] ?? defaultValue) * scale; let bezier = 0; for (let frame = 0; ; frame++) { timeline.setFrame(frame, time, value1, value2); - let nextMap = keys[frame + 1]; + const nextMap = keys[frame + 1]; if (!nextMap) { timeline.shrink(bezier); timelines.push(timeline); return; } - let time2 = getValue(nextMap, "time", 0); - let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; - let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; - let curve = keyMap.curve; + const time2 = nextMap.time ?? 0; + const nvalue1 = (nextMap[name1] ?? defaultValue) * scale; + const nvalue2 = (nextMap[name2] ?? defaultValue) * scale; + const curve = keyMap.curve; if (curve) { bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); @@ -1295,21 +1309,22 @@ function readTimeline2 (timelines: Array, keys: any[], timeline: BoneT } } -function readCurve (curve: any, timeline: CurveTimeline, bezier: number, frame: number, value: number, time1: number, time2: number, +function readCurve (curve: [number, number, number, number] | "stepped", timeline: CurveTimeline, bezier: number, frame: number, value: number, time1: number, time2: number, value1: number, value2: number, scale: number) { - if (curve == "stepped") { + if (curve === "stepped") { timeline.setStepped(frame); return bezier; } - let i = value << 2; - let cx1 = curve[i]; - let cy1 = curve[i + 1] * scale; - let cx2 = curve[i + 2]; - let cy2 = curve[i + 3] * scale; + const i = value << 2; + const cx1 = curve[i]; + const cy1 = curve[i + 1] * scale; + const cx2 = curve[i + 2]; + const cy2 = curve[i + 3] * scale; timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); return bezier + 1; } +// biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema function getValue (map: any, property: string, defaultValue: any) { return map[property] !== undefined ? map[property] : defaultValue; } diff --git a/spine-ts/spine-core/src/SkeletonRendererCore.ts b/spine-ts/spine-core/src/SkeletonRendererCore.ts index 8ef0ab474..bbf3b727b 100644 --- a/spine-ts/spine-core/src/SkeletonRendererCore.ts +++ b/spine-ts/spine-core/src/SkeletonRendererCore.ts @@ -69,6 +69,7 @@ export class SkeletonRendererCore { let indices: number[] | Uint32Array; let indicesCount: number; let attachmentColor: Color; + // biome-ignore lint/suspicious/noExplicitAny: texture depends on the runtime let texture: any; if (attachment instanceof RegionAttachment) { @@ -270,6 +271,7 @@ interface RenderCommand { numVertices: number; numIndices: number; blendMode: BlendMode; + // biome-ignore lint/suspicious/noExplicitAny: texture depends on the runtime texture: any; next?: RenderCommand; } diff --git a/spine-ts/spine-core/src/Skin.ts b/spine-ts/spine-core/src/Skin.ts index 517496622..b4b6e84d3 100644 --- a/spine-ts/spine-core/src/Skin.ts +++ b/spine-ts/spine-core/src/Skin.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Attachment } from "./attachments/Attachment.js"; +import type { Attachment } from "./attachments/Attachment.js"; import { MeshAttachment } from "./attachments/MeshAttachment.js"; -import { BoneData } from "./BoneData.js"; -import { ConstraintData } from "./ConstraintData.js"; -import { Skeleton } from "./Skeleton.js"; -import { Color, StringMap } from "./Utils.js"; +import type { BoneData } from "./BoneData.js"; +import type { ConstraintData } from "./ConstraintData.js"; +import type { Skeleton } from "./Skeleton.js"; +import { Color, type StringMap } from "./Utils.js"; /** Stores an entry in the skin consisting of the slot index, name, and attachment **/ export class SkinEntry { @@ -47,9 +47,10 @@ export class Skin { /** The skin's name, which is unique across all skins in the skeleton. */ name: string; - attachments = new Array>(); - bones = Array(); - constraints = new Array>(); + attachments = [] as StringMap[]; + bones = [] as BoneData[]; + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constraints = [] as ConstraintData[]; /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ color = new Color(0.99607843, 0.61960787, 0.30980393, 1); // fe9e4fff @@ -62,7 +63,7 @@ export class Skin { /** Adds an attachment to the skin for the specified slot index and name. */ setAttachment (slotIndex: number, name: string, attachment: Attachment) { if (!attachment) throw new Error("attachment cannot be null."); - let attachments = this.attachments; + const attachments = this.attachments; if (slotIndex >= attachments.length) attachments.length = slotIndex + 1; if (!attachments[slotIndex]) attachments[slotIndex] = {}; attachments[slotIndex][name] = attachment; @@ -71,10 +72,10 @@ export class Skin { /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ addSkin (skin: Skin) { for (let i = 0; i < skin.bones.length; i++) { - let bone = skin.bones[i]; + const bone = skin.bones[i]; let contained = false; for (let ii = 0; ii < this.bones.length; ii++) { - if (this.bones[ii] == bone) { + if (this.bones[ii] === bone) { contained = true; break; } @@ -83,10 +84,10 @@ export class Skin { } for (let i = 0; i < skin.constraints.length; i++) { - let constraint = skin.constraints[i]; + const constraint = skin.constraints[i]; let contained = false; for (let ii = 0; ii < this.constraints.length; ii++) { - if (this.constraints[ii] == constraint) { + if (this.constraints[ii] === constraint) { contained = true; break; } @@ -94,9 +95,9 @@ export class Skin { if (!contained) this.constraints.push(constraint); } - let attachments = skin.getAttachments(); + const attachments = skin.getAttachments(); for (let i = 0; i < attachments.length; i++) { - var attachment = attachments[i]; + const attachment = attachments[i]; this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); } } @@ -105,10 +106,10 @@ export class Skin { * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ copySkin (skin: Skin) { for (let i = 0; i < skin.bones.length; i++) { - let bone = skin.bones[i]; + const bone = skin.bones[i]; let contained = false; for (let ii = 0; ii < this.bones.length; ii++) { - if (this.bones[ii] == bone) { + if (this.bones[ii] === bone) { contained = true; break; } @@ -117,10 +118,10 @@ export class Skin { } for (let i = 0; i < skin.constraints.length; i++) { - let constraint = skin.constraints[i]; + const constraint = skin.constraints[i]; let contained = false; for (let ii = 0; ii < this.constraints.length; ii++) { - if (this.constraints[ii] == constraint) { + if (this.constraints[ii] === constraint) { contained = true; break; } @@ -128,9 +129,9 @@ export class Skin { if (!contained) this.constraints.push(constraint); } - let attachments = skin.getAttachments(); + const attachments = skin.getAttachments(); for (let i = 0; i < attachments.length; i++) { - var attachment = attachments[i]; + const attachment = attachments[i]; if (!attachment.attachment) continue; if (attachment.attachment instanceof MeshAttachment) { attachment.attachment = attachment.attachment.newLinkedMesh(); @@ -144,24 +145,24 @@ export class Skin { /** Returns the attachment for the specified slot index and name, or null. */ getAttachment (slotIndex: number, name: string): Attachment | null { - let dictionary = this.attachments[slotIndex]; + const dictionary = this.attachments[slotIndex]; return dictionary ? dictionary[name] : null; } /** Removes the attachment in the skin for the specified slot index and name, if any. */ removeAttachment (slotIndex: number, name: string) { - let dictionary = this.attachments[slotIndex]; + const dictionary = this.attachments[slotIndex]; if (dictionary) delete dictionary[name]; } /** Returns all attachments in this skin. */ getAttachments (): Array { - let entries = new Array(); - for (var i = 0; i < this.attachments.length; i++) { - let slotAttachments = this.attachments[i]; + const entries: SkinEntry[] = []; + for (let i = 0; i < this.attachments.length; i++) { + const slotAttachments = this.attachments[i]; if (slotAttachments) { - for (let name in slotAttachments) { - let attachment = slotAttachments[name]; + for (const name in slotAttachments) { + const attachment = slotAttachments[name]; if (attachment) entries.push(new SkinEntry(i, name, attachment)); } } @@ -171,10 +172,10 @@ export class Skin { /** Returns all attachments in this skin for the specified slot index. */ getAttachmentsForSlot (slotIndex: number, attachments: Array) { - let slotAttachments = this.attachments[slotIndex]; + const slotAttachments = this.attachments[slotIndex]; if (slotAttachments) { - for (let name in slotAttachments) { - let attachment = slotAttachments[name]; + for (const name in slotAttachments) { + const attachment = slotAttachments[name]; if (attachment) attachments.push(new SkinEntry(slotIndex, name, attachment)); } } @@ -191,14 +192,14 @@ export class Skin { attachAll (skeleton: Skeleton, oldSkin: Skin) { let slotIndex = 0; for (let i = 0; i < skeleton.slots.length; i++) { - let slot = skeleton.slots[i]; - let slotAttachment = slot.pose.getAttachment(); + const slot = skeleton.slots[i]; + const slotAttachment = slot.pose.getAttachment(); if (slotAttachment && slotIndex < oldSkin.attachments.length) { - let dictionary = oldSkin.attachments[slotIndex]; - for (let key in dictionary) { - let skinAttachment: Attachment = dictionary[key]; - if (slotAttachment == skinAttachment) { - let attachment = this.getAttachment(slotIndex, key); + const dictionary = oldSkin.attachments[slotIndex]; + for (const key in dictionary) { + const skinAttachment: Attachment = dictionary[key]; + if (slotAttachment === skinAttachment) { + const attachment = this.getAttachment(slotIndex, key); if (attachment) slot.pose.setAttachment(attachment); break; } diff --git a/spine-ts/spine-core/src/SliderData.ts b/spine-ts/spine-core/src/SliderData.ts index 8e3139dcf..0e6e490e8 100644 --- a/spine-ts/spine-core/src/SliderData.ts +++ b/spine-ts/spine-core/src/SliderData.ts @@ -27,13 +27,13 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation } from "./Animation.js"; -import { BoneData } from "./BoneData.js"; +import type { Animation } from "./Animation.js"; +import type { BoneData } from "./BoneData.js"; import { ConstraintData } from "./ConstraintData.js"; -import { Skeleton } from "./Skeleton.js"; +import type { Skeleton } from "./Skeleton.js"; import { Slider } from "./Slider.js"; import { SliderPose } from "./SliderPose.js"; -import { FromProperty } from "./TransformConstraintData.js"; +import type { FromProperty } from "./TransformConstraintData.js"; /** Stores the setup pose for a {@link SliderConstraint}. * diff --git a/spine-ts/spine-core/src/SliderPose.ts b/spine-ts/spine-core/src/SliderPose.ts index 5569b7280..5df4cf5eb 100644 --- a/spine-ts/spine-core/src/SliderPose.ts +++ b/spine-ts/spine-core/src/SliderPose.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose.js"; +import type { Pose } from "./Pose.js"; /** Stores a pose for a slider. */ export class SliderPose implements Pose { diff --git a/spine-ts/spine-core/src/Slot.ts b/spine-ts/spine-core/src/Slot.ts index 716bf2c1d..8c61df540 100644 --- a/spine-ts/spine-core/src/Slot.ts +++ b/spine-ts/spine-core/src/Slot.ts @@ -27,10 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Bone } from "./Bone.js"; +import type { Bone } from "./Bone.js"; import { Posed } from "./Posed.js"; -import { Skeleton } from "./Skeleton.js"; -import { SlotData } from "./SlotData.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { SlotData } from "./SlotData.js"; import { SlotPose } from "./SlotPose.js"; import { Color } from "./Utils.js"; @@ -59,6 +59,7 @@ export class Slot extends Posed { setupPose () { this.pose.color.setFromColor(this.data.setup.color); + // biome-ignore lint/style/noNonNullAssertion: reference runtime if (this.pose.darkColor) this.pose.darkColor.setFromColor(this.data.setup.darkColor!); this.pose.sequenceIndex = this.data.setup.sequenceIndex; if (!this.data.attachmentName) diff --git a/spine-ts/spine-core/src/SlotData.ts b/spine-ts/spine-core/src/SlotData.ts index 6ea7d07f6..62d4ba1b1 100644 --- a/spine-ts/spine-core/src/SlotData.ts +++ b/spine-ts/spine-core/src/SlotData.ts @@ -27,11 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { BoneData } from "./BoneData.js"; +import type { BoneData } from "./BoneData.js"; import { PosedData } from "./PosedData.js"; -import { SlotPose } from "./SlotPose.js"; - import type { Skeleton } from "./Skeleton.js"; +import { SlotPose } from "./SlotPose.js"; /** Stores the setup pose for a {@link Slot}. */ export class SlotData extends PosedData { diff --git a/spine-ts/spine-core/src/SlotPose.ts b/spine-ts/spine-core/src/SlotPose.ts index 6c16445db..e7f73372d 100644 --- a/spine-ts/spine-core/src/SlotPose.ts +++ b/spine-ts/spine-core/src/SlotPose.ts @@ -27,11 +27,11 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose.js"; -import { Color } from "./Utils.js"; +import type { Attachment } from "./attachments/Attachment.js"; import { VertexAttachment } from "./attachments/Attachment.js"; -import { Attachment } from "./attachments/Attachment.js"; import type { Sequence } from "./attachments/Sequence.js"; +import type { Pose } from "./Pose.js"; +import { Color } from "./Utils.js"; /** Stores a slot's pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store state * for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared across @@ -57,7 +57,7 @@ export class SlotPose implements Pose { * * See {@link VertexAttachment.computeWorldVertices()} and * {@link DeformTimeline}. */ - readonly deform = new Array(); + readonly deform = [] as number[]; SlotPose () { } @@ -81,9 +81,9 @@ export class SlotPose implements Pose { * The deform is not cleared if the old attachment has the same {@link VertexAttachment.getTimelineAttachment()} as the * specified attachment. */ setAttachment (attachment: Attachment | null): void { - if (this.attachment == attachment) return; + if (this.attachment === attachment) return; if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) - || attachment.timelineAttachment != this.attachment.timelineAttachment) { + || attachment.timelineAttachment !== this.attachment.timelineAttachment) { this.deform.length = 0; } this.attachment = attachment; diff --git a/spine-ts/spine-core/src/Texture.ts b/spine-ts/spine-core/src/Texture.ts index 701eaede2..657cd900c 100644 --- a/spine-ts/spine-core/src/Texture.ts +++ b/spine-ts/spine-core/src/Texture.ts @@ -27,6 +27,8 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +/** biome-ignore-all lint/suspicious/noExplicitAny: textures can be various type */ + export abstract class Texture { protected _image: HTMLImageElement | ImageBitmap | any; diff --git a/spine-ts/spine-core/src/TextureAtlas.ts b/spine-ts/spine-core/src/TextureAtlas.ts index 688faf92e..f3bf82674 100644 --- a/spine-ts/spine-core/src/TextureAtlas.ts +++ b/spine-ts/spine-core/src/TextureAtlas.ts @@ -27,86 +27,86 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { AssetManagerBase } from "./AssetManagerBase.js"; -import { TextureFilter, TextureWrap, Texture, TextureRegion } from "./Texture.js"; -import { Disposable, Utils, StringMap } from "./Utils.js"; +import type { AssetManagerBase } from "./AssetManagerBase.js"; +import { type Texture, TextureFilter, TextureRegion, TextureWrap } from "./Texture.js"; +import { type Disposable, type StringMap, Utils } from "./Utils.js"; export class TextureAtlas implements Disposable { - pages = new Array(); - regions = new Array(); + pages = [] as TextureAtlasPage[]; + regions = [] as TextureAtlasRegion[]; constructor (atlasText: string) { - let reader = new TextureAtlasReader(atlasText); - let entry = new Array(4); + const reader = new TextureAtlasReader(atlasText); + const entry = new Array(4); - let pageFields: StringMap<(page: TextureAtlasPage) => void> = {}; - pageFields["size"] = (page: TextureAtlasPage) => { - page!.width = parseInt(entry[1]); - page!.height = parseInt(entry[2]); + const pageFields: StringMap<(page: TextureAtlasPage) => void> = {}; + pageFields.size = (page: TextureAtlasPage) => { + page.width = parseInt(entry[1]); + page.height = parseInt(entry[2]); }; - pageFields["format"] = () => { + pageFields.format = () => { // page.format = Format[tuple[0]]; we don't need format in WebGL }; - pageFields["filter"] = (page: TextureAtlasPage) => { - page!.minFilter = Utils.enumValue(TextureFilter, entry[1]); - page!.magFilter = Utils.enumValue(TextureFilter, entry[2]); + pageFields.filter = (page: TextureAtlasPage) => { + page.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page.magFilter = Utils.enumValue(TextureFilter, entry[2]); }; - pageFields["repeat"] = (page: TextureAtlasPage) => { - if (entry[1].indexOf('x') != -1) page!.uWrap = TextureWrap.Repeat; - if (entry[1].indexOf('y') != -1) page!.vWrap = TextureWrap.Repeat; + pageFields.repeat = (page: TextureAtlasPage) => { + if (entry[1].indexOf('x') !== -1) page.uWrap = TextureWrap.Repeat; + if (entry[1].indexOf('y') !== -1) page.vWrap = TextureWrap.Repeat; }; - pageFields["pma"] = (page: TextureAtlasPage) => { - page!.pma = entry[1] == "true"; + pageFields.pma = (page: TextureAtlasPage) => { + page.pma = entry[1] === "true"; }; var regionFields: StringMap<(region: TextureAtlasRegion) => void> = {}; - regionFields["xy"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds. + regionFields.xy = (region: TextureAtlasRegion) => { // Deprecated, use bounds. region.x = parseInt(entry[1]); region.y = parseInt(entry[2]); }; - regionFields["size"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds. + regionFields.size = (region: TextureAtlasRegion) => { // Deprecated, use bounds. region.width = parseInt(entry[1]); region.height = parseInt(entry[2]); }; - regionFields["bounds"] = (region: TextureAtlasRegion) => { + regionFields.bounds = (region: TextureAtlasRegion) => { region.x = parseInt(entry[1]); region.y = parseInt(entry[2]); region.width = parseInt(entry[3]); region.height = parseInt(entry[4]); }; - regionFields["offset"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets. + regionFields.offset = (region: TextureAtlasRegion) => { // Deprecated, use offsets. region.offsetX = parseInt(entry[1]); region.offsetY = parseInt(entry[2]); }; - regionFields["orig"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets. + regionFields.orig = (region: TextureAtlasRegion) => { // Deprecated, use offsets. region.originalWidth = parseInt(entry[1]); region.originalHeight = parseInt(entry[2]); }; - regionFields["offsets"] = (region: TextureAtlasRegion) => { + regionFields.offsets = (region: TextureAtlasRegion) => { region.offsetX = parseInt(entry[1]); region.offsetY = parseInt(entry[2]); region.originalWidth = parseInt(entry[3]); region.originalHeight = parseInt(entry[4]); }; - regionFields["rotate"] = (region: TextureAtlasRegion) => { - let value = entry[1]; - if (value == "true") + regionFields.rotate = (region: TextureAtlasRegion) => { + const value = entry[1]; + if (value === "true") region.degrees = 90; - else if (value != "false") + else if (value !== "false") region.degrees = parseInt(value); }; - regionFields["index"] = (region: TextureAtlasRegion) => { + regionFields.index = (region: TextureAtlasRegion) => { region.index = parseInt(entry[1]); }; let line = reader.readLine(); // Ignore empty lines before first entry. - while (line && line.trim().length == 0) + while (line && line.trim().length === 0) line = reader.readLine(); // Header entries. while (true) { - if (!line || line.trim().length == 0) break; - if (reader.readEntry(entry, line) == 0) break; // Silently ignore all header fields. + if (!line || line.trim().length === 0) break; + if (reader.readEntry(entry, line) === 0) break; // Silently ignore all header fields. line = reader.readLine(); } @@ -116,37 +116,37 @@ export class TextureAtlas implements Disposable { let values: number[][] | null = null; while (true) { if (line === null) break; - if (line.trim().length == 0) { + if (line.trim().length === 0) { page = null; line = reader.readLine(); } else if (!page) { page = new TextureAtlasPage(line.trim()); while (true) { - if (reader.readEntry(entry, line = reader.readLine()) == 0) break; - let field = pageFields[entry[0]]; + if (reader.readEntry(entry, line = reader.readLine()) === 0) break; + const field = pageFields[entry[0]]; if (field) field(page); } this.pages.push(page); } else { - let region = new TextureAtlasRegion(page, line); + const region = new TextureAtlasRegion(page, line); while (true) { - let count = reader.readEntry(entry, line = reader.readLine()); - if (count == 0) break; - let field = regionFields[entry[0]]; + const count = reader.readEntry(entry, line = reader.readLine()); + if (count === 0) break; + const field = regionFields[entry[0]]; if (field) field(region); else { if (!names) names = []; if (!values) values = []; names.push(entry[0]); - let entryValues: number[] = []; + const entryValues: number[] = []; for (let i = 0; i < count; i++) entryValues.push(parseInt(entry[i + 1])); values.push(entryValues); } } - if (region.originalWidth == 0 && region.originalHeight == 0) { + if (region.originalWidth === 0 && region.originalHeight === 0) { region.originalWidth = region.width; region.originalHeight = region.height; } @@ -158,7 +158,7 @@ export class TextureAtlas implements Disposable { } region.u = region.x / page.width; region.v = region.y / page.height; - if (region.degrees == 90) { + if (region.degrees === 90) { region.u2 = (region.x + region.height) / page.width; region.v2 = (region.y + region.width) / page.height; } else { @@ -172,7 +172,7 @@ export class TextureAtlas implements Disposable { findRegion (name: string): TextureAtlasRegion | null { for (let i = 0; i < this.regions.length; i++) { - if (this.regions[i].name == name) { + if (this.regions[i].name === name) { return this.regions[i]; } } @@ -180,8 +180,8 @@ export class TextureAtlas implements Disposable { } setTextures (assetManager: AssetManagerBase, pathPrefix: string = "") { - for (let page of this.pages) - page.setTexture(assetManager.get(pathPrefix + page.name)); + for (const page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name) as Texture); } dispose () { @@ -208,20 +208,20 @@ class TextureAtlasReader { readEntry (entry: string[], line: string | null): number { if (!line) return 0; line = line.trim(); - if (line.length == 0) return 0; + if (line.length === 0) return 0; - let colon = line.indexOf(':'); - if (colon == -1) return 0; + const colon = line.indexOf(':'); + if (colon === -1) return 0; entry[0] = line.substr(0, colon).trim(); for (let i = 1, lastMatch = colon + 1; ; i++) { - let comma = line.indexOf(',', lastMatch); - if (comma == -1) { + const comma = line.indexOf(',', lastMatch); + if (comma === -1) { entry[i] = line.substr(lastMatch).trim(); return i; } entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); lastMatch = comma + 1; - if (i == 4) return 4; + if (i === 4) return 4; } } } @@ -236,7 +236,7 @@ export class TextureAtlasPage { width: number = 0; height: number = 0; pma: boolean = false; - regions = new Array(); + regions = [] as TextureAtlasRegion[]; constructor (name: string) { this.name = name; @@ -246,7 +246,7 @@ export class TextureAtlasPage { this.texture = texture; texture.setFilters(this.minFilter, this.magFilter); texture.setWraps(this.uWrap, this.vWrap); - for (let region of this.regions) + for (const region of this.regions) region.texture = texture; } } diff --git a/spine-ts/spine-core/src/TransformConstraint.ts b/spine-ts/spine-core/src/TransformConstraint.ts index 9124de7fb..04dc064c9 100644 --- a/spine-ts/spine-core/src/TransformConstraint.ts +++ b/spine-ts/spine-core/src/TransformConstraint.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Bone } from "./Bone.js"; -import { BonePose } from "./BonePose.js"; +import type { Bone } from "./Bone.js"; +import type { BonePose } from "./BonePose.js"; import { Constraint } from "./Constraint.js"; -import { Physics } from "./Physics.js"; -import { Skeleton } from "./Skeleton.js"; -import { TransformConstraintData } from "./TransformConstraintData.js"; +import type { Physics } from "./Physics.js"; +import type { Skeleton } from "./Skeleton.js"; +import type { TransformConstraintData } from "./TransformConstraintData.js"; import { TransformConstraintPose } from "./TransformConstraintPose.js"; import { MathUtils } from "./Utils.js"; @@ -53,7 +53,7 @@ export class TransformConstraint extends Constraint(); + this.bones = [] as BonePose[]; for (const boneData of data.bones) this.bones.push(skeleton.bones[boneData.index].constrained); @@ -70,7 +70,7 @@ export class TransformConstraint extends Constraint(); + bones = [] as BoneData[]; /** The bone whose world transform will be copied to the constrained bones. */ public set source (source: BoneData) { this._source = source; } @@ -275,7 +275,7 @@ export class ToScaleX extends ToProperty { if (local) { if (additive) bone.scaleX *= 1 + (value - 1) * pose.mixScaleX; - else if (bone.scaleX != 0) // + else if (bone.scaleX !== 0) // bone.scaleX += (value - bone.scaleX) * pose.mixScaleX; } else if (additive) { const s = 1 + (value - 1) * pose.mixScaleX; @@ -283,7 +283,7 @@ export class ToScaleX extends ToProperty { bone.c *= s; } else { let a = bone.a / skeleton.scaleX, c = bone.c / skeleton.scaleY, s = Math.sqrt(a * a + c * c); - if (s != 0) { + if (s !== 0) { s = 1 + (value - s) * pose.mixScaleX / s; bone.a *= s; bone.c *= s; @@ -309,7 +309,7 @@ export class ToScaleY extends ToProperty { if (local) { if (additive) bone.scaleY *= 1 + (value - 1) * pose.mixScaleY; - else if (bone.scaleY != 0) // + else if (bone.scaleY !== 0) // bone.scaleY += (value - bone.scaleY) * pose.mixScaleY; } else if (additive) { const s = 1 + (value - 1) * pose.mixScaleY; @@ -317,7 +317,7 @@ export class ToScaleY extends ToProperty { bone.d *= s; } else { let b = bone.b / skeleton.scaleX, d = bone.d / skeleton.scaleY, s = Math.sqrt(b * b + d * d); - if (s != 0) { + if (s !== 0) { s = 1 + (value - s) * pose.mixScaleY / s; bone.b *= s; bone.d *= s; diff --git a/spine-ts/spine-core/src/TransformConstraintPose.ts b/spine-ts/spine-core/src/TransformConstraintPose.ts index f8167a1cd..9d160c4ae 100644 --- a/spine-ts/spine-core/src/TransformConstraintPose.ts +++ b/spine-ts/spine-core/src/TransformConstraintPose.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Pose } from "./Pose" +import type { Pose } from "./Pose" /** Stores a pose for a transform constraint. */ export class TransformConstraintPose implements Pose { diff --git a/spine-ts/spine-core/src/Triangulator.ts b/spine-ts/spine-core/src/Triangulator.ts index 8f790cc62..ff5f6c112 100644 --- a/spine-ts/spine-core/src/Triangulator.ts +++ b/spine-ts/spine-core/src/Triangulator.ts @@ -27,55 +27,56 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { NumberArrayLike, Pool } from "./Utils.js"; +import { type NumberArrayLike, Pool } from "./Utils.js"; export class Triangulator { - private convexPolygons = new Array>(); - private convexPolygonsIndices = new Array>(); + private convexPolygons = [] as Array[]; + private convexPolygonsIndices = [] as Array[]; - private indicesArray = new Array(); - private isConcaveArray = new Array(); - private triangles = new Array(); + private indicesArray = [] as number[]; + private isConcaveArray = [] as boolean[]; + private triangles = [] as number[]; private polygonPool = new Pool>(() => { - return new Array(); + return [] as number[]; }); private polygonIndicesPool = new Pool>(() => { - return new Array(); + return [] as number[]; }); public triangulate (verticesArray: NumberArrayLike): Array { - let vertices = verticesArray; + const vertices = verticesArray; let vertexCount = verticesArray.length >> 1; - let indices = this.indicesArray; + const indices = this.indicesArray; indices.length = 0; for (let i = 0; i < vertexCount; i++) indices[i] = i; - let isConcave = this.isConcaveArray; + const isConcave = this.isConcaveArray; isConcave.length = 0; for (let i = 0, n = vertexCount; i < n; ++i) isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); - let triangles = this.triangles; + const triangles = this.triangles; triangles.length = 0; while (vertexCount > 3) { // Find ear tip. let previous = vertexCount - 1, i = 0, next = 1; while (true) { + // biome-ignore lint/suspicious/noConfusingLabels: reference runtime outer: if (!isConcave[i]) { - let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; - let p1x = vertices[p1], p1y = vertices[p1 + 1]; - let p2x = vertices[p2], p2y = vertices[p2 + 1]; - let p3x = vertices[p3], p3y = vertices[p3 + 1]; - for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + const p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + const p1x = vertices[p1], p1y = vertices[p1 + 1]; + const p2x = vertices[p2], p2y = vertices[p2 + 1]; + const p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii !== previous; ii = (ii + 1) % vertexCount) { if (!isConcave[ii]) continue; - let v = indices[ii] << 1; - let vx = vertices[v], vy = vertices[v + 1]; + const v = indices[ii] << 1; + const vx = vertices[v], vy = vertices[v + 1]; if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer; @@ -85,7 +86,7 @@ export class Triangulator { break; } - if (next == 0) { + if (next === 0) { do { if (!isConcave[i]) break; i--; @@ -106,13 +107,13 @@ export class Triangulator { isConcave.splice(i, 1); vertexCount--; - let previousIndex = (vertexCount + i - 1) % vertexCount; - let nextIndex = i == vertexCount ? 0 : i; + const previousIndex = (vertexCount + i - 1) % vertexCount; + const nextIndex = i === vertexCount ? 0 : i; isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); } - if (vertexCount == 3) { + if (vertexCount === 3) { triangles.push(indices[2]); triangles.push(indices[0]); triangles.push(indices[1]); @@ -122,12 +123,12 @@ export class Triangulator { } decompose (verticesArray: Array, triangles: Array): Array> { - let vertices = verticesArray; - let convexPolygons = this.convexPolygons; + const vertices = verticesArray; + const convexPolygons = this.convexPolygons; this.polygonPool.freeAll(convexPolygons); convexPolygons.length = 0; - let convexPolygonsIndices = this.convexPolygonsIndices; + const convexPolygonsIndices = this.convexPolygonsIndices; this.polygonIndicesPool.freeAll(convexPolygonsIndices); convexPolygonsIndices.length = 0; @@ -140,18 +141,18 @@ export class Triangulator { // Merge subsequent triangles if they form a triangle fan. let fanBaseIndex = -1, lastWinding = 0; for (let i = 0, n = triangles.length; i < n; i += 3) { - let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; - let x1 = vertices[t1], y1 = vertices[t1 + 1]; - let x2 = vertices[t2], y2 = vertices[t2 + 1]; - let x3 = vertices[t3], y3 = vertices[t3 + 1]; + const t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + const x1 = vertices[t1], y1 = vertices[t1 + 1]; + const x2 = vertices[t2], y2 = vertices[t2 + 1]; + const x3 = vertices[t3], y3 = vertices[t3 + 1]; // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). let merged = false; - if (fanBaseIndex == t1) { - let o = polygon.length - 4; - let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); - let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); - if (winding1 == lastWinding && winding2 == lastWinding) { + if (fanBaseIndex === t1) { + const o = polygon.length - 4; + const winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + const winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 === lastWinding && winding2 === lastWinding) { polygon.push(x3); polygon.push(y3); polygonIndices.push(t3); @@ -194,33 +195,33 @@ export class Triangulator { // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. for (let i = 0, n = convexPolygons.length; i < n; i++) { polygonIndices = convexPolygonsIndices[i]; - if (polygonIndices.length == 0) continue; - let firstIndex = polygonIndices[0]; - let lastIndex = polygonIndices[polygonIndices.length - 1]; + if (polygonIndices.length === 0) continue; + const firstIndex = polygonIndices[0]; + const lastIndex = polygonIndices[polygonIndices.length - 1]; polygon = convexPolygons[i]; - let o = polygon.length - 4; + const o = polygon.length - 4; let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; let prevX = polygon[o + 2], prevY = polygon[o + 3]; - let firstX = polygon[0], firstY = polygon[1]; - let secondX = polygon[2], secondY = polygon[3]; - let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + const firstX = polygon[0], firstY = polygon[1]; + const secondX = polygon[2], secondY = polygon[3]; + const winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); for (let ii = 0; ii < n; ii++) { - if (ii == i) continue; - let otherIndices = convexPolygonsIndices[ii]; - if (otherIndices.length != 3) continue; - let otherFirstIndex = otherIndices[0]; - let otherSecondIndex = otherIndices[1]; - let otherLastIndex = otherIndices[2]; + if (ii === i) continue; + const otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length !== 3) continue; + const otherFirstIndex = otherIndices[0]; + const otherSecondIndex = otherIndices[1]; + const otherLastIndex = otherIndices[2]; - let otherPoly = convexPolygons[ii]; - let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + const otherPoly = convexPolygons[ii]; + const x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; - if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; - let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); - let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); - if (winding1 == winding && winding2 == winding) { + if (otherFirstIndex !== firstIndex || otherSecondIndex !== lastIndex) continue; + const winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + const winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 === winding && winding2 === winding) { otherPoly.length = 0; otherIndices.length = 0; polygon.push(x3); @@ -238,7 +239,7 @@ export class Triangulator { // Remove empty polygons that resulted from the merge step above. for (let i = convexPolygons.length - 1; i >= 0; i--) { polygon = convexPolygons[i]; - if (polygon.length == 0) { + if (polygon.length === 0) { convexPolygons.splice(i, 1); this.polygonPool.free(polygon); polygonIndices = convexPolygonsIndices[i] @@ -251,10 +252,10 @@ export class Triangulator { } private static isConcave (index: number, vertexCount: number, vertices: NumberArrayLike, indices: NumberArrayLike): boolean { - let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; - let current = indices[index] << 1; - let next = indices[(index + 1) % vertexCount] << 1; - return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], + const previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + const current = indices[index] << 1; + const next = indices[(index + 1) % vertexCount] << 1; + return !Triangulator.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); } @@ -263,7 +264,7 @@ export class Triangulator { } private static winding (p1x: number, p1y: number, p2x: number, p2y: number, p3x: number, p3y: number): number { - let px = p2x - p1x, py = p2y - p1y; + const px = p2x - p1x, py = p2y - p1y; return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; } } diff --git a/spine-ts/spine-core/src/Utils.ts b/spine-ts/spine-core/src/Utils.ts index e9255fc59..6079fef00 100644 --- a/spine-ts/spine-core/src/Utils.ts +++ b/spine-ts/spine-core/src/Utils.ts @@ -27,24 +27,26 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Skeleton } from "./Skeleton.js"; -import { MixBlend } from "./Animation.js"; +/** biome-ignore-all lint/complexity/noStaticOnlyClass: too much things to update */ + +import type { MixBlend } from "./Animation.js"; +import type { Skeleton } from "./Skeleton.js"; export interface StringMap { [key: string]: T; } export class IntSet { - array = new Array(); + array = [] as (number | undefined)[]; add (value: number): boolean { - let contains = this.contains(value); + const contains = this.contains(value); this.array[value | 0] = value | 0; return !contains; } contains (value: number) { - return this.array[value | 0] != undefined; + return this.array[value | 0] !== undefined; } remove (value: number) { @@ -61,7 +63,7 @@ export class StringSet { size = 0; add (value: string): boolean { - let contains = this.entries[value]; + const contains = this.entries[value]; this.entries[value] = true; if (!contains) { this.size++; @@ -71,10 +73,10 @@ export class StringSet { } addAll (values: string[]): boolean { - let oldSize = this.size; - for (var i = 0, n = values.length; i < n; i++) + const oldSize = this.size; + for (let i = 0, n = values.length; i < n; i++) this.add(values[i]); - return oldSize != this.size; + return oldSize !== this.size; } contains (value: string) { @@ -125,11 +127,11 @@ export class Color { } setFromString (hex: string) { - hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + hex = hex.charAt(0) === '#' ? hex.substr(1) : hex; this.r = parseInt(hex.substr(0, 2), 16) / 255; this.g = parseInt(hex.substr(2, 2), 16) / 255; this.b = parseInt(hex.substr(4, 2), 16) / 255; - this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + this.a = hex.length !== 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; return this; } @@ -170,8 +172,8 @@ export class Color { } toRgb888 () { - const hex = (x: number) => ("0" + (x * 255).toString(16)).slice(-2); - return Number("0x" + hex(this.r) + hex(this.g) + hex(this.b)); + const hex = (x: number) => (`0${(x * 255).toString(16)}`).slice(-2); + return Number(`0x${hex(this.r)}${hex(this.g)}${hex(this.b)}`); } static fromString (hex: string, color = new Color()): Color { @@ -180,6 +182,7 @@ export class Color { } export class MathUtils { + // biome-ignore lint/suspicious/noApproximativeNumericConstant: reference runtime static PI = 3.1415927; static PI2 = MathUtils.PI * 2; static invPI2 = 1 / MathUtils.PI2; @@ -215,7 +218,7 @@ export class MathUtils { } static cbrt (x: number) { - let y = Math.pow(Math.abs(x), 1 / 3); + const y = Math.pow(Math.abs(x), 1 / 3); return x < 0 ? -y : y; } @@ -224,8 +227,8 @@ export class MathUtils { } static randomTriangularWith (min: number, max: number, mode: number): number { - let u = Math.random(); - let d = max - min; + const u = Math.random(); + const d = max - min; if (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min)); return max - Math.sqrt((1 - u) * d * (max - mode)); } @@ -252,7 +255,7 @@ export class Pow extends Interpolation { applyInternal (a: number): number { if (a <= 0.5) return Math.pow(a * 2, this.power) / 2; - return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 === 0 ? -2 : 2) + 1; } } @@ -262,7 +265,7 @@ export class PowOut extends Pow { } applyInternal (a: number): number { - return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + return Math.pow(a - 1, this.power) * (this.power % 2 === 0 ? -1 : 1) + 1; } } @@ -280,9 +283,10 @@ export class Utils { array[i] = value; } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case static setArraySize (array: Array, size: number, value: any = 0): Array { - let oldSize = array.length; - if (oldSize == size) return array; + const oldSize = array.length; + if (oldSize === size) return array; array.length = size; if (oldSize < size) { for (let i = oldSize; i < size; i++) array[i] = value; @@ -290,13 +294,14 @@ export class Utils { return array; } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case static ensureArrayCapacity (array: Array, size: number, value: any = 0): Array { if (array.length >= size) return array; return Utils.setArraySize(array, size, value); } static newArray (size: number, defaultValue: T): Array { - let array = new Array(size); + const array = new Array(size); for (let i = 0; i < size; i++) array[i] = defaultValue; return array; } @@ -305,7 +310,7 @@ export class Utils { if (Utils.SUPPORTS_TYPED_ARRAYS) return new Float32Array(size) else { - let array = new Array(size); + const array = new Array(size); for (let i = 0; i < array.length; i++) array[i] = 0; return array; } @@ -315,7 +320,7 @@ export class Utils { if (Utils.SUPPORTS_TYPED_ARRAYS) return new Int16Array(size) else { - let array = new Array(size); + const array = new Array(size); for (let i = 0; i < array.length; i++) array[i] = 0; return array; } @@ -334,11 +339,12 @@ export class Utils { } static contains (array: Array, element: T, identity = true) { - for (var i = 0; i < array.length; i++) - if (array[i] == element) return true; + for (let i = 0; i < array.length; i++) + if (array[i] === element) return true; return false; } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case static enumValue (type: any, name: string) { return type[name[0].toUpperCase() + name.slice(1)]; } @@ -347,14 +353,14 @@ export class Utils { export class DebugUtils { static logBones (skeleton: Skeleton) { for (let i = 0; i < skeleton.bones.length; i++) { - let bone = skeleton.bones[i].applied; - console.log(bone.bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + const bone = skeleton.bones[i].applied; + console.log(`${bone.bone.data.name}, ${bone.a}, ${bone.b}, ${bone.c}, ${bone.d}, ${bone.worldX}, ${bone.worldY}`); } } } export class Pool { - private items = new Array(); + private items = [] as T[]; private instantiator: () => T; constructor (instantiator: () => T) { @@ -362,11 +368,13 @@ export class Pool { } obtain () { + // biome-ignore lint/style/noNonNullAssertion: length check return this.items.length > 0 ? this.items.pop()! : this.instantiator(); } free (item: T) { - if ((item as any).reset) (item as any).reset(); + // biome-ignore lint/suspicious/noExplicitAny: T can be anything + (item as any).reset?.(); this.items.push(item); } @@ -391,14 +399,14 @@ export class Vector2 { } length () { - let x = this.x; - let y = this.y; + const x = this.x; + const y = this.y; return Math.sqrt(x * x + y * y); } normalize () { - let len = this.length(); - if (len != 0) { + const len = this.length(); + if (len !== 0) { this.x /= len; this.y /= len; } @@ -417,7 +425,7 @@ export class TimeKeeper { private frameTime = 0; update () { - let now = Date.now() / 1000; + const now = Date.now() / 1000; this.delta = now - this.lastTime; this.frameTime += this.delta; this.totalTime += this.delta; diff --git a/spine-ts/spine-core/src/attachments/Attachment.ts b/spine-ts/spine-core/src/attachments/Attachment.ts index f884dc4dd..4a5de7a50 100644 --- a/spine-ts/spine-core/src/attachments/Attachment.ts +++ b/spine-ts/spine-core/src/attachments/Attachment.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Skeleton } from "src/Skeleton.js"; -import { Slot } from "../Slot.js"; -import { NumberArrayLike, Utils } from "../Utils.js"; +import type { Skeleton } from "src/Skeleton.js"; +import type { Slot } from "../Slot.js"; +import { type NumberArrayLike, Utils } from "../Utils.js"; /** The base class for all attachments. */ export abstract class Attachment { @@ -88,17 +88,17 @@ export abstract class VertexAttachment extends Attachment { stride: number) { count = offset + (count >> 1) * stride; - let deformArray = slot.applied.deform; + const deformArray = slot.applied.deform; let vertices = this.vertices; - let bones = this.bones; + const bones = this.bones; if (!bones) { if (deformArray.length > 0) vertices = deformArray; - let bone = slot.bone.applied; - let x = bone.worldX; - let y = bone.worldY; - let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + const bone = slot.bone.applied; + const x = bone.worldX; + const y = bone.worldY; + const a = bone.a, b = bone.b, c = bone.c, d = bone.d; for (let v = start, w = offset; w < count; v += 2, w += stride) { - let vx = vertices[v], vy = vertices[v + 1]; + const vx = vertices[v], vy = vertices[v + 1]; worldVertices[w] = vx * a + vy * b + x; worldVertices[w + 1] = vx * c + vy * d + y; } @@ -106,19 +106,19 @@ export abstract class VertexAttachment extends Attachment { } let v = 0, skip = 0; for (let i = 0; i < start; i += 2) { - let n = bones[v]; + const n = bones[v]; v += n + 1; skip += n; } - let skeletonBones = skeleton.bones; - if (deformArray.length == 0) { + const skeletonBones = skeleton.bones; + if (deformArray.length === 0) { for (let w = offset, b = skip * 3; w < count; w += stride) { let wx = 0, wy = 0; let n = bones[v++]; n += v; for (; v < n; v++, b += 3) { - let bone = skeletonBones[bones[v]].applied; - let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + const bone = skeletonBones[bones[v]].applied; + const vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } @@ -126,14 +126,14 @@ export abstract class VertexAttachment extends Attachment { worldVertices[w + 1] = wy; } } else { - let deform = deformArray; + const deform = deformArray; for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { let wx = 0, wy = 0; let n = bones[v++]; n += v; for (; v < n; v++, b += 3, f += 2) { - let bone = skeletonBones[bones[v]].applied; - let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + const bone = skeletonBones[bones[v]].applied; + const vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } diff --git a/spine-ts/spine-core/src/attachments/AttachmentLoader.ts b/spine-ts/spine-core/src/attachments/AttachmentLoader.ts index cfa6be42d..e0b2e7024 100644 --- a/spine-ts/spine-core/src/attachments/AttachmentLoader.ts +++ b/spine-ts/spine-core/src/attachments/AttachmentLoader.ts @@ -27,14 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Skin } from "../Skin.js"; -import { BoundingBoxAttachment } from "./BoundingBoxAttachment.js"; -import { ClippingAttachment } from "./ClippingAttachment.js"; -import { MeshAttachment } from "./MeshAttachment.js"; -import { PathAttachment } from "./PathAttachment.js"; -import { PointAttachment } from "./PointAttachment.js"; -import { RegionAttachment } from "./RegionAttachment.js"; -import { Sequence } from "./Sequence.js"; +import type { Skin } from "../Skin.js"; +import type { BoundingBoxAttachment } from "./BoundingBoxAttachment.js"; +import type { ClippingAttachment } from "./ClippingAttachment.js"; +import type { MeshAttachment } from "./MeshAttachment.js"; +import type { PathAttachment } from "./PathAttachment.js"; +import type { PointAttachment } from "./PointAttachment.js"; +import type { RegionAttachment } from "./RegionAttachment.js"; +import type { Sequence } from "./Sequence.js"; /** The interface which can be implemented to customize creating and populating attachments. * diff --git a/spine-ts/spine-core/src/attachments/BoundingBoxAttachment.ts b/spine-ts/spine-core/src/attachments/BoundingBoxAttachment.ts index b27dda251..1fe108a60 100644 --- a/spine-ts/spine-core/src/attachments/BoundingBoxAttachment.ts +++ b/spine-ts/spine-core/src/attachments/BoundingBoxAttachment.ts @@ -28,7 +28,7 @@ *****************************************************************************/ import { Color } from "../Utils.js"; -import { VertexAttachment, Attachment } from "./Attachment.js"; +import { type Attachment, VertexAttachment } from "./Attachment.js"; /** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle * effects, and more. @@ -43,7 +43,7 @@ export class BoundingBoxAttachment extends VertexAttachment { } copy (): Attachment { - let copy = new BoundingBoxAttachment(this.name); + const copy = new BoundingBoxAttachment(this.name); this.copyTo(copy); copy.color.setFromColor(this.color); return copy; diff --git a/spine-ts/spine-core/src/attachments/ClippingAttachment.ts b/spine-ts/spine-core/src/attachments/ClippingAttachment.ts index b42c2eb7e..d37b66166 100644 --- a/spine-ts/spine-core/src/attachments/ClippingAttachment.ts +++ b/spine-ts/spine-core/src/attachments/ClippingAttachment.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { SlotData } from "../SlotData.js"; +import type { SlotData } from "../SlotData.js"; import { Color } from "../Utils.js"; -import { VertexAttachment, Attachment } from "./Attachment.js"; +import { type Attachment, VertexAttachment } from "./Attachment.js"; /** An attachment with vertices that make up a polygon used for clipping the rendering of other attachments. */ export class ClippingAttachment extends VertexAttachment { @@ -47,7 +47,7 @@ export class ClippingAttachment extends VertexAttachment { } copy (): Attachment { - let copy = new ClippingAttachment(this.name); + const copy = new ClippingAttachment(this.name); this.copyTo(copy); copy.endSlot = this.endSlot; copy.color.setFromColor(this.color); diff --git a/spine-ts/spine-core/src/attachments/HasTextureRegion.ts b/spine-ts/spine-core/src/attachments/HasTextureRegion.ts index 0555fdcc9..b2fbb2126 100644 --- a/spine-ts/spine-core/src/attachments/HasTextureRegion.ts +++ b/spine-ts/spine-core/src/attachments/HasTextureRegion.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { TextureRegion } from "../Texture.js" -import { Color } from "../Utils.js" -import { Sequence } from "./Sequence.js" +import type { TextureRegion } from "../Texture.js" +import type { Color } from "../Utils.js" +import type { Sequence } from "./Sequence.js" export interface HasTextureRegion { /** The name used to find the {@link #region()}. */ diff --git a/spine-ts/spine-core/src/attachments/MeshAttachment.ts b/spine-ts/spine-core/src/attachments/MeshAttachment.ts index be75a1c89..d0adfa27b 100644 --- a/spine-ts/spine-core/src/attachments/MeshAttachment.ts +++ b/spine-ts/spine-core/src/attachments/MeshAttachment.ts @@ -27,14 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { TextureRegion } from "../Texture.js"; +import type { Skeleton } from "src/Skeleton.js"; +import type { Slot } from "../Slot.js"; +import type { TextureRegion } from "../Texture.js"; import { TextureAtlasRegion } from "../TextureAtlas.js"; -import { Color, NumberArrayLike, Utils } from "../Utils.js"; -import { VertexAttachment, Attachment } from "./Attachment.js"; -import { HasTextureRegion } from "./HasTextureRegion.js"; -import { Sequence } from "./Sequence.js"; -import { Slot } from "../Slot.js"; -import { Skeleton } from "src/Skeleton.js"; +import { Color, type NumberArrayLike, Utils } from "../Utils.js"; +import { type Attachment, VertexAttachment } from "./Attachment.js"; +import type { HasTextureRegion } from "./HasTextureRegion.js"; +import type { Sequence } from "./Sequence.js"; /** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not * supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh. @@ -88,14 +88,14 @@ export class MeshAttachment extends VertexAttachment implements HasTextureRegion * the {@link #regionUVs} are changed. */ updateRegion () { if (!this.region) throw new Error("Region not set."); - let regionUVs = this.regionUVs; - if (!this.uvs || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length); - let uvs = this.uvs; - let n = this.uvs.length; + const regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length !== regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length); + const uvs = this.uvs; + const n = this.uvs.length; let u = this.region.u, v = this.region.v, width = 0, height = 0; if (this.region instanceof TextureAtlasRegion) { - let region = this.region, page = region.page; - let textureWidth = page.width, textureHeight = page.height; + const region = this.region, page = region.page; + const textureWidth = page.width, textureHeight = page.height; switch (region.degrees) { case 90: u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; @@ -171,7 +171,7 @@ export class MeshAttachment extends VertexAttachment implements HasTextureRegion copy (): Attachment { if (this.parentMesh) return this.newLinkedMesh(); - let copy = new MeshAttachment(this.name, this.path); + const copy = new MeshAttachment(this.name, this.path); copy.region = this.region; copy.color.setFromColor(this.color); @@ -204,7 +204,7 @@ export class MeshAttachment extends VertexAttachment implements HasTextureRegion /** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/ newLinkedMesh (): MeshAttachment { - let copy = new MeshAttachment(this.name, this.path); + const copy = new MeshAttachment(this.name, this.path); copy.region = this.region; copy.color.setFromColor(this.color); copy.timelineAttachment = this.timelineAttachment; diff --git a/spine-ts/spine-core/src/attachments/PathAttachment.ts b/spine-ts/spine-core/src/attachments/PathAttachment.ts index 330fcd6ab..b02218729 100644 --- a/spine-ts/spine-core/src/attachments/PathAttachment.ts +++ b/spine-ts/spine-core/src/attachments/PathAttachment.ts @@ -28,7 +28,7 @@ *****************************************************************************/ import { Color, Utils } from "../Utils.js"; -import { VertexAttachment, Attachment } from "./Attachment.js"; +import { type Attachment, VertexAttachment } from "./Attachment.js"; /** An attachment whose vertices make up a composite Bezier curve. * @@ -54,7 +54,7 @@ export class PathAttachment extends VertexAttachment { } copy (): Attachment { - let copy = new PathAttachment(this.name); + const copy = new PathAttachment(this.name); this.copyTo(copy); copy.lengths = new Array(this.lengths.length); Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); diff --git a/spine-ts/spine-core/src/attachments/PointAttachment.ts b/spine-ts/spine-core/src/attachments/PointAttachment.ts index fffac9060..ca6d62940 100644 --- a/spine-ts/spine-core/src/attachments/PointAttachment.ts +++ b/spine-ts/spine-core/src/attachments/PointAttachment.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { BonePose } from "src/BonePose.js"; -import { Color, Vector2, MathUtils } from "../Utils.js"; -import { VertexAttachment, Attachment } from "./Attachment.js"; +import type { BonePose } from "src/BonePose.js"; +import { Color, MathUtils, type Vector2 } from "../Utils.js"; +import { type Attachment, VertexAttachment } from "./Attachment.js"; /** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be * used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a @@ -63,7 +63,7 @@ export class PointAttachment extends VertexAttachment { } copy (): Attachment { - let copy = new PointAttachment(this.name); + const copy = new PointAttachment(this.name); copy.x = this.x; copy.y = this.y; copy.rotation = this.rotation; diff --git a/spine-ts/spine-core/src/attachments/RegionAttachment.ts b/spine-ts/spine-core/src/attachments/RegionAttachment.ts index 35834359e..a87507abd 100644 --- a/spine-ts/spine-core/src/attachments/RegionAttachment.ts +++ b/spine-ts/spine-core/src/attachments/RegionAttachment.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { TextureRegion } from "../Texture.js"; -import { Color, MathUtils, NumberArrayLike, Utils } from "../Utils.js"; +import type { Slot } from "../Slot.js"; +import type { TextureRegion } from "../Texture.js"; +import { Color, MathUtils, type NumberArrayLike, Utils } from "../Utils.js"; import { Attachment } from "./Attachment.js"; -import { HasTextureRegion } from "./HasTextureRegion.js"; -import { Sequence } from "./Sequence.js"; -import { Slot } from "../Slot.js"; +import type { HasTextureRegion } from "./HasTextureRegion.js"; +import type { Sequence } from "./Sequence.js"; /** An attachment that displays a textured quadrilateral. * @@ -85,27 +85,27 @@ export class RegionAttachment extends Attachment implements HasTextureRegion { /** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */ updateRegion (): void { if (!this.region) throw new Error("Region not set."); - let region = this.region; - let uvs = this.uvs; - let regionScaleX = this.width / this.region.originalWidth * this.scaleX; - let regionScaleY = this.height / this.region.originalHeight * this.scaleY; - let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; - let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; - let localX2 = localX + this.region.width * regionScaleX; - let localY2 = localY + this.region.height * regionScaleY; - let radians = this.rotation * MathUtils.degRad; - let cos = Math.cos(radians); - let sin = Math.sin(radians); - let x = this.x, y = this.y; - let localXCos = localX * cos + x; - let localXSin = localX * sin; - let localYCos = localY * cos + y; - let localYSin = localY * sin; - let localX2Cos = localX2 * cos + x; - let localX2Sin = localX2 * sin; - let localY2Cos = localY2 * cos + y; - let localY2Sin = localY2 * sin; - let offset = this.offset; + const region = this.region; + const uvs = this.uvs; + const regionScaleX = this.width / this.region.originalWidth * this.scaleX; + const regionScaleY = this.height / this.region.originalHeight * this.scaleY; + const localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + const localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + const localX2 = localX + this.region.width * regionScaleX; + const localY2 = localY + this.region.height * regionScaleY; + const radians = this.rotation * MathUtils.degRad; + const cos = Math.cos(radians); + const sin = Math.sin(radians); + const x = this.x, y = this.y; + const localXCos = localX * cos + x; + const localXSin = localX * sin; + const localYCos = localY * cos + y; + const localYSin = localY * sin; + const localX2Cos = localX2 * cos + x; + const localX2Sin = localX2 * sin; + const localY2Cos = localY2 * cos + y; + const localY2Sin = localY2 * sin; + const offset = this.offset; offset[0] = localXCos - localYSin; offset[1] = localYCos + localXSin; offset[2] = localXCos - localY2Sin; @@ -124,7 +124,7 @@ export class RegionAttachment extends Attachment implements HasTextureRegion { uvs[5] = 1; uvs[6] = 1; uvs[7] = 0; - } else if (region.degrees == 90) { + } else if (region.degrees === 90) { uvs[0] = region.u2; uvs[1] = region.v2; uvs[2] = region.u; @@ -156,10 +156,10 @@ export class RegionAttachment extends Attachment implements HasTextureRegion { computeWorldVertices (slot: Slot, worldVertices: NumberArrayLike, offset: number, stride: number) { if (this.sequence) this.sequence.apply(slot.applied, this); - let bone = slot.bone.applied; - let vertexOffset = this.offset; - let x = bone.worldX, y = bone.worldY; - let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + const bone = slot.bone.applied; + const vertexOffset = this.offset; + const x = bone.worldX, y = bone.worldY; + const a = bone.a, b = bone.b, c = bone.c, d = bone.d; let offsetX = 0, offsetY = 0; offsetX = vertexOffset[0]; @@ -187,7 +187,7 @@ export class RegionAttachment extends Attachment implements HasTextureRegion { } copy (): Attachment { - let copy = new RegionAttachment(this.name, this.path); + const copy = new RegionAttachment(this.name, this.path); copy.region = this.region; copy.x = this.x; copy.y = this.y; diff --git a/spine-ts/spine-core/src/polyfills.ts b/spine-ts/spine-core/src/polyfills.ts index efa76b717..1e8d73654 100644 --- a/spine-ts/spine-core/src/polyfills.ts +++ b/spine-ts/spine-core/src/polyfills.ts @@ -29,10 +29,9 @@ (() => { if (typeof Math.fround === "undefined") { - Math.fround = (function (array) { - return function (x: number) { - return array[0] = x, array[0]; - }; + Math.fround = ((array) => (x: number) => { + array[0] = x; + return array[0]; })(new Float32Array(1)); } })(); diff --git a/spine-ts/spine-player/src/Player.ts b/spine-ts/spine-player/src/Player.ts index 8de243c47..fb2cc68eb 100644 --- a/spine-ts/spine-player/src/Player.ts +++ b/spine-ts/spine-player/src/Player.ts @@ -919,7 +919,7 @@ export class SpinePlayer implements Disposable { // Draw the background image. let bgImage = config.backgroundImage; if (bgImage) { - let texture = this.assetManager!.require(bgImage.url); + let texture = this.assetManager!.require(bgImage.url) as GLTexture; if (bgImage.x !== void 0 && bgImage.y !== void 0 && bgImage.width && bgImage.height) renderer.drawTexture(texture, bgImage.x, bgImage.y, bgImage.width, bgImage.height); else diff --git a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts index 42e898038..69cce4411 100644 --- a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts +++ b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts @@ -978,7 +978,8 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable const skeletonLoader = isBinary ? new SkeletonBinary(atlasLoader) : new SkeletonJson(atlasLoader); skeletonLoader.scale = scale; - const skeletonFileAsset = this.overlay.assetManager.require(skeletonPath); + // biome-ignore lint/suspicious/noExplicitAny: it is any untile we have a json schema + const skeletonFileAsset = this.overlay.assetManager.require(skeletonPath) as Record; const skeletonFile = this.jsonSkeletonKey ? skeletonFileAsset[this.jsonSkeletonKey] : skeletonFileAsset; const skeletonData = (skeletonDataInput || this.skeleton?.data) ?? skeletonLoader.readSkeletonData(skeletonFile);