From c3ac62d1ddaedfd6e7008c7d9ef16d13bff170b2 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Mon, 27 Oct 2025 10:57:30 +0100 Subject: [PATCH] [ts] Processed spine-ts (not player) with biome. --- spine-ts/assets/mask_empty.json | 64 ++++ spine-ts/biome.json | 3 +- spine-ts/spine-canvas/src/CanvasTexture.ts | 2 +- spine-ts/spine-canvas/src/SkeletonRenderer.ts | 106 +++---- spine-ts/spine-canvas/src/index.ts | 4 +- spine-ts/spine-canvaskit/src/index.ts | 1 + .../spine-phaser-v3/src/SpineGameObject.ts | 83 +++--- spine-ts/spine-phaser-v3/src/SpinePlugin.ts | 1 - spine-ts/spine-phaser-v3/src/index.ts | 16 +- spine-ts/spine-phaser-v3/src/mixins.ts | 4 +- spine-ts/spine-phaser-v3/src/require-shim.ts | 4 +- .../spine-phaser-v4/src/SpineGameObject.ts | 87 +++--- spine-ts/spine-phaser-v4/src/index.ts | 45 ++- spine-ts/spine-phaser-v4/src/mixins.ts | 4 +- spine-ts/spine-phaser-v4/src/require-shim.ts | 4 +- spine-ts/spine-pixi-v7/src/DarkSlotMesh.ts | 6 +- spine-ts/spine-pixi-v7/src/SlotMesh.ts | 10 +- spine-ts/spine-pixi-v7/src/Spine.ts | 8 +- .../spine-pixi-v7/src/SpineDebugRenderer.ts | 9 +- spine-ts/spine-pixi-v7/src/SpineTexture.ts | 8 +- .../spine-pixi-v7/src/assets/AtlasLoader.ts | 12 +- .../src/assets/SkeletonLoader.ts | 11 +- .../src/darkTintMesh/DarkTintBatchGeom.ts | 2 +- .../src/darkTintMesh/DarkTintGeom.ts | 2 +- .../src/darkTintMesh/DarkTintMaterial.ts | 6 +- .../src/darkTintMesh/DarkTintMesh.ts | 6 +- .../src/darkTintMesh/DarkTintRenderer.ts | 6 +- spine-ts/spine-pixi-v7/src/index.ts | 48 ++- spine-ts/spine-pixi-v7/src/require-shim.ts | 4 +- .../spine-pixi-v8/src/BatchableSpineSlot.ts | 14 +- spine-ts/spine-pixi-v8/src/Spine.ts | 34 ++- .../spine-pixi-v8/src/SpineDebugRenderer.ts | 16 +- spine-ts/spine-pixi-v8/src/SpinePipe.ts | 7 +- spine-ts/spine-pixi-v8/src/SpineTexture.ts | 3 +- .../spine-pixi-v8/src/assets/AtlasLoader.ts | 3 +- .../src/assets/SkeletonLoader.ts | 7 +- .../src/darktint/DarkTintBatcher.ts | 8 +- spine-ts/spine-pixi-v8/src/index.ts | 2 +- spine-ts/spine-pixi-v8/src/require-shim.ts | 2 + spine-ts/spine-player/src/Player.ts | 273 +++++++++--------- spine-ts/spine-player/src/PlayerEditor.ts | 4 +- spine-ts/spine-player/src/index.ts | 6 +- .../src/SpineWebComponentOverlay.ts | 103 +++---- .../src/SpineWebComponentSkeleton.ts | 67 ++--- spine-ts/spine-webcomponents/src/index.ts | 4 +- spine-ts/spine-webgl/src/AssetManager.ts | 2 +- spine-ts/spine-webgl/src/Camera.ts | 12 +- spine-ts/spine-webgl/src/CameraController.ts | 28 +- spine-ts/spine-webgl/src/GLTexture.ts | 14 +- spine-ts/spine-webgl/src/Input.ts | 79 ++--- spine-ts/spine-webgl/src/LoadingScreen.ts | 22 +- spine-ts/spine-webgl/src/Matrix4.ts | 60 ++-- spine-ts/spine-webgl/src/Mesh.ts | 30 +- spine-ts/spine-webgl/src/PolygonBatcher.ts | 33 ++- spine-ts/spine-webgl/src/SceneRenderer.ts | 55 ++-- spine-ts/spine-webgl/src/Shader.ts | 46 +-- spine-ts/spine-webgl/src/ShapeRenderer.ts | 97 +++---- .../spine-webgl/src/SkeletonDebugRenderer.ts | 88 +++--- spine-ts/spine-webgl/src/SkeletonRenderer.ts | 52 ++-- spine-ts/spine-webgl/src/SpineCanvas.ts | 8 +- spine-ts/spine-webgl/src/Vector3.ts | 16 +- spine-ts/spine-webgl/src/index.ts | 4 +- 62 files changed, 956 insertions(+), 809 deletions(-) create mode 100644 spine-ts/assets/mask_empty.json diff --git a/spine-ts/assets/mask_empty.json b/spine-ts/assets/mask_empty.json new file mode 100644 index 000000000..0a532a9fe --- /dev/null +++ b/spine-ts/assets/mask_empty.json @@ -0,0 +1,64 @@ +{ + "skeleton": { + "hash": "kUVJGzLCHio", + "spine": "4.2.43", + "x": -66, + "y": -141.5, + "width": 142, + "height": 232, + "images": "./images/", + "audio": "./audio" + }, + "bones": [ + { "name": "root" }, + { "name": "empty_1", "parent": "root", "x": -44, "y": 53.5 }, + { "name": "empty_8", "parent": "root", "x": 5, "y": -104.5 }, + { "name": "empty_7", "parent": "root", "x": -44, "y": -104.5 }, + { "name": "empty_6", "parent": "root", "x": 54, "y": -25.5 }, + { "name": "empty_5", "parent": "root", "x": 5, "y": -25.5 }, + { "name": "empty_4", "parent": "root", "x": -44, "y": -25.5 }, + { "name": "empty_3", "parent": "root", "x": 54, "y": 53.5 }, + { "name": "empty_2", "parent": "root", "x": 5, "y": 53.5 } + ], + "slots": [ + { "name": "mask", "bone": "root", "attachment": "mask" }, + { "name": "empty_1", "bone": "empty_1", "attachment": "empty" }, + { "name": "empty_2", "bone": "empty_2", "attachment": "empty" }, + { "name": "empty_3", "bone": "empty_3", "attachment": "empty" }, + { "name": "empty_4", "bone": "empty_4", "attachment": "empty" }, + { "name": "empty_5", "bone": "empty_5", "attachment": "empty" }, + { "name": "empty_6", "bone": "empty_6", "attachment": "empty" }, + { "name": "empty_7", "bone": "empty_7", "attachment": "empty" }, + { "name": "empty_8", "bone": "empty_8", "attachment": "empty" } + ], + "skins": [ + { + "name": "default", + "attachments": { + "empty_1": { "empty": { "width": 44, "height": 74 } }, + "empty_2": { "empty": { "width": 44, "height": 74 } }, + "empty_3": { "empty": { "width": 44, "height": 74 } }, + "empty_4": { "empty": { "width": 44, "height": 74 } }, + "empty_5": { "empty": { "width": 44, "height": 74 } }, + "empty_6": { "empty": { "width": 44, "height": 74 } }, + "empty_7": { "empty": { "width": 44, "height": 74 } }, + "empty_8": { "empty": { "width": 44, "height": 74 } }, + "mask": { + "mask": { + "type": "clipping", + "end": "mask", + "vertexCount": 16, + "vertices": [ + -53.67, -27.41, -147.5, -13.5, -65, 33.5, -92.5, 70.5, -21.01, + 32.95, 12.5, 114.5, 36.79, 30.32, 129.5, 66.5, 93, 30.5, 124.5, + -5.5, 98, -51.5, 139.5, -97.5, 38.8, -65.21, -9.5, -181.5, -26.27, + -70.62, -106.5, -105.5 + ], + "color": "ce3a3aff" + } + } + } + } + ], + "animations": { "animation": {} } +} diff --git a/spine-ts/biome.json b/spine-ts/biome.json index 3de998f02..2f11ef6b5 100644 --- a/spine-ts/biome.json +++ b/spine-ts/biome.json @@ -16,7 +16,8 @@ "useExponentiationOperator": "off" }, "suspicious": { - "noAssignInExpressions": "off" + "noAssignInExpressions": "off", + "noPrototypeBuiltins": "off" } } } diff --git a/spine-ts/spine-canvas/src/CanvasTexture.ts b/spine-ts/spine-canvas/src/CanvasTexture.ts index 0e0417770..167d27014 100644 --- a/spine-ts/spine-canvas/src/CanvasTexture.ts +++ b/spine-ts/spine-canvas/src/CanvasTexture.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Texture, TextureFilter, TextureWrap } from "@esotericsoftware/spine-core"; +import { Texture, type TextureFilter, type TextureWrap } from "@esotericsoftware/spine-core"; export class CanvasTexture extends Texture { constructor (image: HTMLImageElement | ImageBitmap) { diff --git a/spine-ts/spine-canvas/src/SkeletonRenderer.ts b/spine-ts/spine-canvas/src/SkeletonRenderer.ts index 8d384c4b7..55a78fb65 100644 --- a/spine-ts/spine-canvas/src/SkeletonRenderer.ts +++ b/spine-ts/spine-canvas/src/SkeletonRenderer.ts @@ -27,8 +27,8 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Utils, Color, Skeleton, RegionAttachment, BlendMode, MeshAttachment, Slot, TextureRegion, TextureAtlasRegion } from "@esotericsoftware/spine-core"; -import { CanvasTexture } from "./CanvasTexture.js"; +import { type BlendMode, Color, MeshAttachment, RegionAttachment, type Skeleton, type Slot, type TextureRegion, Utils } from "@esotericsoftware/spine-core"; +import type { CanvasTexture } from "./CanvasTexture.js"; const worldVertices = Utils.newFloatArray(8); @@ -53,28 +53,28 @@ export class SkeletonRenderer { } private drawImages (skeleton: Skeleton) { - let ctx = this.ctx; - let color = this.tempColor; - let skeletonColor = skeleton.color; - let drawOrder = skeleton.drawOrder; + const ctx = this.ctx; + const color = this.tempColor; + const skeletonColor = skeleton.color; + const drawOrder = skeleton.drawOrder; if (this.debugRendering) ctx.strokeStyle = "green"; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; - let bone = slot.bone; + const bone = slot.bone; if (!bone.active) continue; - let pose = slot.applied; - let attachment = pose.attachment; + const pose = slot.applied; + const attachment = pose.attachment; if (!(attachment instanceof RegionAttachment)) continue; attachment.computeWorldVertices(slot, worldVertices, 0, 2); - let region: TextureRegion = attachment.region; + const region: TextureRegion = attachment.region; - let image: HTMLImageElement = (region.texture).getImage() as HTMLImageElement; + const image: HTMLImageElement = (region.texture).getImage() as HTMLImageElement; - let slotColor = pose.color; - let regionColor = attachment.color; + const slotColor = pose.color; + const regionColor = attachment.color; color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, @@ -86,13 +86,13 @@ export class SkeletonRenderer { ctx.translate(attachment.offset[0], attachment.offset[1]); ctx.rotate(attachment.rotation * Math.PI / 180); - let atlasScale = attachment.width / region.originalWidth; + const atlasScale = attachment.width / region.originalWidth; ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); let w = region.width, h = region.height; ctx.translate(w / 2, h / 2); - if (attachment.region!.degrees == 90) { - let t = w; + if (attachment.region?.degrees === 90) { + const t = w; w = h; h = t; ctx.rotate(-Math.PI / 2); @@ -108,10 +108,10 @@ export class SkeletonRenderer { } private drawTriangles (skeleton: Skeleton) { - let ctx = this.ctx; - let color = this.tempColor; - let skeletonColor = skeleton.color; - let drawOrder = skeleton.drawOrder; + const ctx = this.ctx; + const color = this.tempColor; + const skeletonColor = skeleton.color; + const drawOrder = skeleton.drawOrder; let blendMode: BlendMode | null = null; let vertices: ArrayLike = this.vertices; @@ -119,28 +119,28 @@ export class SkeletonRenderer { for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; - let pose = slot.applied; - let attachment = pose.attachment; + const pose = slot.applied; + const attachment = pose.attachment; let texture: HTMLImageElement; if (attachment instanceof RegionAttachment) { - let regionAttachment = attachment; + const regionAttachment = attachment; vertices = this.computeRegionVertices(slot, regionAttachment, false); triangles = SkeletonRenderer.QUAD_TRIANGLES; - texture = (regionAttachment.region!.texture).getImage() as HTMLImageElement; + texture = (regionAttachment.region?.texture).getImage() as HTMLImageElement; } else if (attachment instanceof MeshAttachment) { - let mesh = attachment; + const mesh = attachment; vertices = this.computeMeshVertices(slot, mesh, false); triangles = mesh.triangles; - texture = (mesh.region!.texture).getImage() as HTMLImageElement; + texture = (mesh.region?.texture).getImage() as HTMLImageElement; } else continue; if (texture) { - if (slot.data.blendMode != blendMode) blendMode = slot.data.blendMode; + if (slot.data.blendMode !== blendMode) blendMode = slot.data.blendMode; - let slotColor = pose.color; - let attachmentColor = attachment.color; + const slotColor = pose.color; + const attachmentColor = attachment.color; color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, @@ -148,12 +148,12 @@ export class SkeletonRenderer { ctx.globalAlpha = color.a; - for (var j = 0; j < triangles.length; j += 3) { - let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + for (let j = 0; j < triangles.length; j += 3) { + const t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; - let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; - let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; - let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7]; + const x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + const x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + const x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7]; this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); @@ -178,7 +178,7 @@ export class SkeletonRenderer { private drawTriangle (img: HTMLImageElement, x0: number, y0: number, u0: number, v0: number, x1: number, y1: number, u1: number, v1: number, x2: number, y2: number, u2: number, v2: number) { - let ctx = this.ctx; + const ctx = this.ctx; const width = img.width - 1; const height = img.height - 1; @@ -206,7 +206,7 @@ export class SkeletonRenderer { v2 -= v0; let det = u1 * v2 - u2 * v1; - if (det == 0) return; + if (det === 0) return; det = 1 / det; // linear transformation @@ -227,12 +227,12 @@ export class SkeletonRenderer { } private computeRegionVertices (slot: Slot, region: RegionAttachment, pma: boolean) { - let skeletonColor = slot.skeleton.color; - let slotColor = slot.applied.color; - let regionColor = region.color; - let alpha = skeletonColor.a * slotColor.a * regionColor.a; - let multiplier = pma ? alpha : 1; - let color = this.tempColor; + const skeletonColor = slot.skeleton.color; + const slotColor = slot.applied.color; + const regionColor = region.color; + const alpha = skeletonColor.a * slotColor.a * regionColor.a; + const multiplier = pma ? alpha : 1; + const color = this.tempColor; color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, @@ -240,8 +240,8 @@ export class SkeletonRenderer { region.computeWorldVertices(slot, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE); - let vertices = this.vertices; - let uvs = region.uvs; + const vertices = this.vertices; + const uvs = region.uvs; vertices[RegionAttachment.C1R] = color.r; vertices[RegionAttachment.C1G] = color.g; @@ -275,24 +275,24 @@ export class SkeletonRenderer { } private computeMeshVertices (slot: Slot, mesh: MeshAttachment, pma: boolean) { - let skeleton = slot.skeleton; - let skeletonColor = skeleton.color; - let slotColor = slot.applied.color; - let regionColor = mesh.color; - let alpha = skeletonColor.a * slotColor.a * regionColor.a; - let multiplier = pma ? alpha : 1; - let color = this.tempColor; + const skeleton = slot.skeleton; + const skeletonColor = skeleton.color; + const slotColor = slot.applied.color; + const regionColor = mesh.color; + const alpha = skeletonColor.a * slotColor.a * regionColor.a; + const multiplier = pma ? alpha : 1; + const color = this.tempColor; color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha); - let vertexCount = mesh.worldVerticesLength / 2; + const vertexCount = mesh.worldVerticesLength / 2; let vertices = this.vertices; if (vertices.length < mesh.worldVerticesLength) this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); mesh.computeWorldVertices(skeleton, slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE); - let uvs = mesh.uvs; + const uvs = mesh.uvs; for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { vertices[v++] = color.r; vertices[v++] = color.g; diff --git a/spine-ts/spine-canvas/src/index.ts b/spine-ts/spine-canvas/src/index.ts index b6568d65a..e882fb9aa 100644 --- a/spine-ts/spine-canvas/src/index.ts +++ b/spine-ts/spine-canvas/src/index.ts @@ -1,4 +1,4 @@ +export * from "@esotericsoftware/spine-core" export * from "./AssetManager.js"; export * from "./CanvasTexture.js"; -export * from "./SkeletonRenderer.js"; -export * from "@esotericsoftware/spine-core" \ No newline at end of file +export * from "./SkeletonRenderer.js"; \ No newline at end of file diff --git a/spine-ts/spine-canvaskit/src/index.ts b/spine-ts/spine-canvaskit/src/index.ts index 34a82de43..ace308937 100644 --- a/spine-ts/spine-canvaskit/src/index.ts +++ b/spine-ts/spine-canvaskit/src/index.ts @@ -245,6 +245,7 @@ export class SkeletonRenderer { positions, uvs, colors, + // biome-ignore lint/suspicious/noExplicitAny: canvaskit wants indices as an array of number indices as any as number[], false ); diff --git a/spine-ts/spine-phaser-v3/src/SpineGameObject.ts b/spine-ts/spine-phaser-v3/src/SpineGameObject.ts index a7dfe15e0..4f9114494 100644 --- a/spine-ts/spine-phaser-v3/src/SpineGameObject.ts +++ b/spine-ts/spine-phaser-v3/src/SpineGameObject.ts @@ -27,29 +27,29 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; -import { SpinePlugin } from "./SpinePlugin.js"; -import { - ComputedSizeMixin, - DepthMixin, - FlipMixin, - ScrollFactorMixin, - TransformMixin, - VisibleMixin, - AlphaMixin, - OriginMixin, -} from "./mixins.js"; import { AnimationState, AnimationStateData, - Bone, + type Bone, MathUtils, Physics, Skeleton, SkeletonClipping, Skin, - Vector2, + type Vector2, } from "@esotericsoftware/spine-core"; +import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; +import { + AlphaMixin, + ComputedSizeMixin, + DepthMixin, + FlipMixin, + OriginMixin, + ScrollFactorMixin, + TransformMixin, + VisibleMixin, +} from "./mixins.js"; +import type { SpinePlugin } from "./SpinePlugin.js"; class BaseSpineGameObject extends Phaser.GameObjects.GameObject { constructor (scene: Phaser.Scene, type: string) { @@ -99,7 +99,7 @@ export class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider { skeleton.setupPose(); skeleton.updateWorldTransform(Physics.update); const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined); - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } @@ -137,7 +137,7 @@ export class SkinsAndAnimationBoundsProvider const clipper = this.clipping ? new SkeletonClipping() : undefined; const data = skeleton.data; if (this.skins.length > 0) { - let customSkin = new Skin("custom-skin"); + const customSkin = new Skin("custom-skin"); for (const skinName of this.skins) { const skin = data.findSkin(skinName); if (skin == null) continue; @@ -147,12 +147,11 @@ export class SkinsAndAnimationBoundsProvider } skeleton.setupPose(); - const animation = - this.animation != null ? data.findAnimation(this.animation!) : null; + const animation = this.animation != null ? data.findAnimation(this.animation) : null; if (animation == null) { skeleton.updateWorldTransform(Physics.update); const bounds = skeleton.getBoundsRect(clipper); - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } else { @@ -182,7 +181,7 @@ export class SkinsAndAnimationBoundsProvider width: maxX - minX, height: maxY - minY, }; - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } @@ -240,6 +239,7 @@ export class SpineGameObject extends DepthMixin( atlasKey: string, public boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider() ) { + // biome-ignore lint/suspicious/noExplicitAny: necessary super(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE); this.setPosition(x, y); @@ -253,7 +253,7 @@ export class SpineGameObject extends DepthMixin( updateSize () { if (!this.skeleton) return; - let bounds = this.boundsProvider.calculateBounds(this); + const bounds = this.boundsProvider.calculateBounds(this); this.width = bounds.width; this.height = bounds.height; this.setDisplayOrigin(-bounds.x, -bounds.y); @@ -263,15 +263,15 @@ export class SpineGameObject extends DepthMixin( /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ skeletonToPhaserWorldCoordinates (point: { x: number; y: number }) { - let transform = this.getWorldTransformMatrix(); - let a = transform.a, + const transform = this.getWorldTransformMatrix(); + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let x = point.x; - let y = point.y; + const x = point.x; + const y = point.y; point.x = x * a + y * c + tx; point.y = x * b + y * d + ty; } @@ -280,14 +280,14 @@ export class SpineGameObject extends DepthMixin( phaserWorldCoordinatesToSkeleton (point: { x: number; y: number }) { let transform = this.getWorldTransformMatrix(); transform = transform.invert(); - let a = transform.a, + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let x = point.x; - let y = point.y; + const x = point.x; + const y = point.y; point.x = x * a + y * c + tx; point.y = x * b + y * d + ty; } @@ -330,7 +330,7 @@ export class SpineGameObject extends DepthMixin( if (!this.visible) result = false; if (!result && this.parentContainer && this.plugin.webGLRenderer) { - var sceneRenderer = this.plugin.webGLRenderer; + const sceneRenderer = this.plugin.webGLRenderer; if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) { sceneRenderer.end(); @@ -350,27 +350,27 @@ export class SpineGameObject extends DepthMixin( if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer) return; - let sceneRenderer = this.plugin.webGLRenderer; + const sceneRenderer = this.plugin.webGLRenderer; if (renderer.newType) { renderer.pipelines.clear(); sceneRenderer.begin(); } camera.addToRenderList(src); - let transform = Phaser.GameObjects.GetCalcMatrix( + const transform = Phaser.GameObjects.GetCalcMatrix( src, camera, parentMatrix ).calc; - let a = transform.a, + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let offsetX = src.offsetX - src.displayOriginX; - let offsetY = src.offsetY - src.displayOriginY; + const offsetX = src.offsetX - src.displayOriginX; + const offsetY = src.offsetY - src.displayOriginY; sceneRenderer.drawSkeleton( src.skeleton, @@ -379,8 +379,8 @@ export class SpineGameObject extends DepthMixin( -1, (vertices, numVertices, stride) => { for (let i = 0; i < numVertices; i += stride) { - let vx = vertices[i] + offsetX; - let vy = vertices[i + 1] + offsetY; + const vx = vertices[i] + offsetX; + const vy = vertices[i + 1] + offsetY; vertices[i] = vx * a + vy * c + tx; vertices[i + 1] = vx * b + vy * d + ty; } @@ -402,22 +402,23 @@ export class SpineGameObject extends DepthMixin( if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) return; - let context = renderer.currentContext; - let skeletonRenderer = this.plugin.canvasRenderer; + const context = renderer.currentContext; + const skeletonRenderer = this.plugin.canvasRenderer; + // biome-ignore lint/suspicious/noExplicitAny: necessary for phaser (skeletonRenderer as any).ctx = context; camera.addToRenderList(src); - let transform = Phaser.GameObjects.GetCalcMatrix( + const transform = Phaser.GameObjects.GetCalcMatrix( src, camera, parentMatrix ).calc; - let skeleton = this.skeleton; + const skeleton = this.skeleton; skeleton.x = transform.tx; skeleton.y = transform.ty; skeleton.scaleX = transform.scaleX; skeleton.scaleY = transform.scaleY; - let root = skeleton.getRootBone()!; + const root = skeleton.getRootBone() as Bone; root.applied.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized; this.skeleton.updateWorldTransform(Physics.update); diff --git a/spine-ts/spine-phaser-v3/src/SpinePlugin.ts b/spine-ts/spine-phaser-v3/src/SpinePlugin.ts index 54402dae9..89a48f6e0 100644 --- a/spine-ts/spine-phaser-v3/src/SpinePlugin.ts +++ b/spine-ts/spine-phaser-v3/src/SpinePlugin.ts @@ -88,7 +88,6 @@ export class SpinePlugin extends Phaser.Plugins.ScenePlugin { constructor (scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) { super(scene, pluginManager, pluginKey); - console.log(pluginKey); this.game = pluginManager.game; this.isWebGL = this.game.config.renderType === 2; this.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null; diff --git a/spine-ts/spine-phaser-v3/src/index.ts b/spine-ts/spine-phaser-v3/src/index.ts index ec012fbbb..3ad594624 100644 --- a/spine-ts/spine-phaser-v3/src/index.ts +++ b/spine-ts/spine-phaser-v3/src/index.ts @@ -27,17 +27,21 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -export * from "./require-shim.js" -export * from "./SpinePlugin.js" -export * from "./SpineGameObject.js" -export * from "./mixins.js" export * from "@esotericsoftware/spine-core"; export * from "@esotericsoftware/spine-webgl"; -import { SpineGameObjectConfig, SpinePlugin } from "./SpinePlugin.js"; +export * from "./mixins.js" +export * from "./require-shim.js" +export * from "./SpineGameObject.js" +export * from "./SpinePlugin.js" + +import { type SpineGameObjectConfig, SpinePlugin } from "./SpinePlugin.js"; + +// biome-ignore lint/suspicious/noExplicitAny: need to add spine to window (window as any).spine = { SpinePlugin: SpinePlugin }; +// biome-ignore lint/suspicious/noExplicitAny: need to add spine to window (window as any)["spine.SpinePlugin"] = SpinePlugin; -import { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; +import type { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; declare global { namespace Phaser.Loader { diff --git a/spine-ts/spine-phaser-v3/src/mixins.ts b/spine-ts/spine-phaser-v3/src/mixins.ts index 836d41c3a..904012386 100644 --- a/spine-ts/spine-phaser-v3/src/mixins.ts +++ b/spine-ts/spine-phaser-v3/src/mixins.ts @@ -24,7 +24,9 @@ SOFTWARE. // Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main -let components = (Phaser.GameObjects.Components as any); +// biome-ignore-all lint: ignore biome for this file + +const components = (Phaser.GameObjects.Components as any); export const ComputedSize = components.ComputedSize; export const Depth = components.Depth; export const Flip = components.Flip; diff --git a/spine-ts/spine-phaser-v3/src/require-shim.ts b/spine-ts/spine-phaser-v3/src/require-shim.ts index 8644aa40b..fa0d0b5c5 100644 --- a/spine-ts/spine-phaser-v3/src/require-shim.ts +++ b/spine-ts/spine-phaser-v3/src/require-shim.ts @@ -27,8 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +// biome-ignore-all lint: ignore biome for this file + if (typeof window !== 'undefined' && window.Phaser) { - let prevRequire = window.require; + const prevRequire = window.require; (window as any).require = (x: string) => { if (prevRequire) return prevRequire(x); else if (x === "Phaser") return window.Phaser; diff --git a/spine-ts/spine-phaser-v4/src/SpineGameObject.ts b/spine-ts/spine-phaser-v4/src/SpineGameObject.ts index 3c89abcf1..c5235042d 100644 --- a/spine-ts/spine-phaser-v4/src/SpineGameObject.ts +++ b/spine-ts/spine-phaser-v4/src/SpineGameObject.ts @@ -27,29 +27,29 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; -import { SpinePlugin } from "./SpinePlugin.js"; -import { - ComputedSizeMixin, - DepthMixin, - FlipMixin, - ScrollFactorMixin, - TransformMixin, - VisibleMixin, - AlphaMixin, - OriginMixin, -} from "./mixins.js"; import { AnimationState, AnimationStateData, - Bone, + type Bone, MathUtils, Physics, Skeleton, SkeletonClipping, Skin, - Vector2, + type Vector2, } from "@esotericsoftware/spine-core"; +import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; +import { + AlphaMixin, + ComputedSizeMixin, + DepthMixin, + FlipMixin, + OriginMixin, + ScrollFactorMixin, + TransformMixin, + VisibleMixin, +} from "./mixins.js"; +import type { SpinePlugin } from "./SpinePlugin.js"; class BaseSpineGameObject extends Phaser.GameObjects.GameObject { constructor (scene: Phaser.Scene, type: string) { @@ -99,7 +99,7 @@ export class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider { skeleton.setupPose(); skeleton.updateWorldTransform(Physics.update); const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined); - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } @@ -137,7 +137,7 @@ export class SkinsAndAnimationBoundsProvider const clipper = this.clipping ? new SkeletonClipping() : undefined; const data = skeleton.data; if (this.skins.length > 0) { - let customSkin = new Skin("custom-skin"); + const customSkin = new Skin("custom-skin"); for (const skinName of this.skins) { const skin = data.findSkin(skinName); if (skin == null) continue; @@ -147,12 +147,11 @@ export class SkinsAndAnimationBoundsProvider } skeleton.setupPose(); - const animation = - this.animation != null ? data.findAnimation(this.animation!) : null; + const animation = this.animation != null ? data.findAnimation(this.animation) : null; if (animation == null) { skeleton.updateWorldTransform(Physics.update); const bounds = skeleton.getBoundsRect(clipper); - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } else { @@ -182,7 +181,7 @@ export class SkinsAndAnimationBoundsProvider width: maxX - minX, height: maxY - minY, }; - return bounds.width == Number.NEGATIVE_INFINITY + return bounds.width === Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; } @@ -240,6 +239,7 @@ export class SpineGameObject extends DepthMixin( atlasKey: string, public boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider() ) { + // biome-ignore lint/suspicious/noExplicitAny: necessary for phaser super(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE); this.setPosition(x, y); @@ -253,7 +253,7 @@ export class SpineGameObject extends DepthMixin( updateSize () { if (!this.skeleton) return; - let bounds = this.boundsProvider.calculateBounds(this); + const bounds = this.boundsProvider.calculateBounds(this); this.width = bounds.width; this.height = bounds.height; this.setDisplayOrigin(-bounds.x, -bounds.y); @@ -263,15 +263,15 @@ export class SpineGameObject extends DepthMixin( /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ skeletonToPhaserWorldCoordinates (point: { x: number; y: number }) { - let transform = this.getWorldTransformMatrix(); - let a = transform.a, + const transform = this.getWorldTransformMatrix(); + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let x = point.x; - let y = point.y; + const x = point.x; + const y = point.y; point.x = x * a + y * c + tx; point.y = x * b + y * d + ty; } @@ -280,14 +280,14 @@ export class SpineGameObject extends DepthMixin( phaserWorldCoordinatesToSkeleton (point: { x: number; y: number }) { let transform = this.getWorldTransformMatrix(); transform = transform.invert(); - let a = transform.a, + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let x = point.x; - let y = point.y; + const x = point.x; + const y = point.y; point.x = x * a + y * c + tx; point.y = x * b + y * d + ty; } @@ -325,12 +325,12 @@ export class SpineGameObject extends DepthMixin( } willRender (camera: Phaser.Cameras.Scene2D.Camera) { - var GameObjectRenderMask = 0xf; - var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id)); + const GameObjectRenderMask = 0xf; + let result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id)); if (!this.visible) result = false; if (!result && this.parentContainer && this.plugin.webGLRenderer) { - var sceneRenderer = this.plugin.webGLRenderer; + const sceneRenderer = this.plugin.webGLRenderer; if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) { sceneRenderer.end(); @@ -354,7 +354,7 @@ export class SpineGameObject extends DepthMixin( if (!camera || !src.skeleton || !src.animationState || !src.plugin.webGLRenderer) return; - let sceneRenderer = src.plugin.webGLRenderer; + const sceneRenderer = src.plugin.webGLRenderer; // Determine object type in context. const previousGameObject = displayList[displayListIndex - 1]; @@ -376,20 +376,20 @@ export class SpineGameObject extends DepthMixin( } camera.addToRenderList(src); - let transform = Phaser.GameObjects.GetCalcMatrix( + const transform = Phaser.GameObjects.GetCalcMatrix( src, camera, parentMatrix ).calc; - let a = transform.a, + const a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; - let offsetX = src.offsetX - src.displayOriginX; - let offsetY = src.offsetY - src.displayOriginY; + const offsetX = src.offsetX - src.displayOriginX; + const offsetY = src.offsetY - src.displayOriginY; sceneRenderer.drawSkeleton( src.skeleton, @@ -398,8 +398,8 @@ export class SpineGameObject extends DepthMixin( -1, (vertices, numVertices, stride) => { for (let i = 0; i < numVertices; i += stride) { - let vx = vertices[i] + offsetX; - let vy = vertices[i + 1] + offsetY; + const vx = vertices[i] + offsetX; + const vy = vertices[i + 1] + offsetY; vertices[i] = vx * a + vy * c + tx; vertices[i + 1] = vx * b + vy * d + ty; } @@ -424,22 +424,23 @@ export class SpineGameObject extends DepthMixin( if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) return; - let context = renderer.currentContext; - let skeletonRenderer = this.plugin.canvasRenderer; + const context = renderer.currentContext; + const skeletonRenderer = this.plugin.canvasRenderer; + // biome-ignore lint/suspicious/noExplicitAny: necessary for phaser (skeletonRenderer as any).ctx = context; camera.addToRenderList(src); - let transform = Phaser.GameObjects.GetCalcMatrix( + const transform = Phaser.GameObjects.GetCalcMatrix( src, camera, parentMatrix ).calc; - let skeleton = this.skeleton; + const skeleton = this.skeleton; skeleton.x = transform.tx; skeleton.y = transform.ty; skeleton.scaleX = transform.scaleX; skeleton.scaleY = transform.scaleY; - let root = skeleton.getRootBone()!; + const root = skeleton.getRootBone() as Bone; root.applied.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized; this.skeleton.updateWorldTransform(Physics.update); diff --git a/spine-ts/spine-phaser-v4/src/index.ts b/spine-ts/spine-phaser-v4/src/index.ts index b5b6f3915..3ad594624 100644 --- a/spine-ts/spine-phaser-v4/src/index.ts +++ b/spine-ts/spine-phaser-v4/src/index.ts @@ -1,14 +1,47 @@ -export * from "./require-shim.js" -export * from "./SpinePlugin.js" -export * from "./SpineGameObject.js" -export * from "./mixins.js" +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + export * from "@esotericsoftware/spine-core"; export * from "@esotericsoftware/spine-webgl"; -import { SpineGameObjectConfig, SpinePlugin } from "./SpinePlugin.js"; +export * from "./mixins.js" +export * from "./require-shim.js" +export * from "./SpineGameObject.js" +export * from "./SpinePlugin.js" + +import { type SpineGameObjectConfig, SpinePlugin } from "./SpinePlugin.js"; + +// biome-ignore lint/suspicious/noExplicitAny: need to add spine to window (window as any).spine = { SpinePlugin: SpinePlugin }; +// biome-ignore lint/suspicious/noExplicitAny: need to add spine to window (window as any)["spine.SpinePlugin"] = SpinePlugin; -import { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; +import type { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; declare global { namespace Phaser.Loader { diff --git a/spine-ts/spine-phaser-v4/src/mixins.ts b/spine-ts/spine-phaser-v4/src/mixins.ts index 836d41c3a..904012386 100644 --- a/spine-ts/spine-phaser-v4/src/mixins.ts +++ b/spine-ts/spine-phaser-v4/src/mixins.ts @@ -24,7 +24,9 @@ SOFTWARE. // Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main -let components = (Phaser.GameObjects.Components as any); +// biome-ignore-all lint: ignore biome for this file + +const components = (Phaser.GameObjects.Components as any); export const ComputedSize = components.ComputedSize; export const Depth = components.Depth; export const Flip = components.Flip; diff --git a/spine-ts/spine-phaser-v4/src/require-shim.ts b/spine-ts/spine-phaser-v4/src/require-shim.ts index 8644aa40b..fa0d0b5c5 100644 --- a/spine-ts/spine-phaser-v4/src/require-shim.ts +++ b/spine-ts/spine-phaser-v4/src/require-shim.ts @@ -27,8 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +// biome-ignore-all lint: ignore biome for this file + if (typeof window !== 'undefined' && window.Phaser) { - let prevRequire = window.require; + const prevRequire = window.require; (window as any).require = (x: string) => { if (prevRequire) return prevRequire(x); else if (x === "Phaser") return window.Phaser; diff --git a/spine-ts/spine-pixi-v7/src/DarkSlotMesh.ts b/spine-ts/spine-pixi-v7/src/DarkSlotMesh.ts index f72d3b668..3989b9c9a 100644 --- a/spine-ts/spine-pixi-v7/src/DarkSlotMesh.ts +++ b/spine-ts/spine-pixi-v7/src/DarkSlotMesh.ts @@ -27,10 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { SpineTexture } from "./SpineTexture.js"; import type { BlendMode, NumberArrayLike } from "@esotericsoftware/spine-core"; import { DarkTintMesh } from "./darkTintMesh/DarkTintMesh.js"; import type { ISlotMesh } from "./Spine.js"; +import { SpineTexture } from "./SpineTexture.js"; export class DarkSlotMesh extends DarkTintMesh implements ISlotMesh { public name: string = ""; @@ -66,8 +66,8 @@ export class DarkSlotMesh extends DarkTintMesh implements ISlotMesh { let vertIndex = 0; - let textureCoordData = textureCoord.data; - let vertexCoordData = vertexCoord.data; + const textureCoordData = textureCoord.data; + const vertexCoordData = vertexCoord.data; for (let i = 0; i < finalVerticesLength; i += darkTint ? 12 : 8) { let auxi = i; diff --git a/spine-ts/spine-pixi-v7/src/SlotMesh.ts b/spine-ts/spine-pixi-v7/src/SlotMesh.ts index 3b8fc8548..eb1e149c7 100644 --- a/spine-ts/spine-pixi-v7/src/SlotMesh.ts +++ b/spine-ts/spine-pixi-v7/src/SlotMesh.ts @@ -27,11 +27,11 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { SpineTexture } from "./SpineTexture.js"; import type { BlendMode, NumberArrayLike } from "@esotericsoftware/spine-core"; -import type { ISlotMesh } from "./Spine.js"; -import { Mesh, MeshGeometry, MeshMaterial } from "@pixi/mesh"; import { Texture } from "@pixi/core"; +import { Mesh, MeshGeometry, MeshMaterial } from "@pixi/mesh"; +import type { ISlotMesh } from "./Spine.js"; +import { SpineTexture } from "./SpineTexture.js"; export class SlotMesh extends Mesh implements ISlotMesh { public name: string = ""; @@ -74,8 +74,8 @@ export class SlotMesh extends Mesh implements ISlotMesh { let vertIndex = 0; - let textureCoordData = textureCoord.data; - let vertexCoordData = vertexCoord.data; + const textureCoordData = textureCoord.data; + const vertexCoordData = vertexCoord.data; for (let i = 0; i < finalVerticesLength; i += darkTint ? 12 : 8) { let auxi = i; diff --git a/spine-ts/spine-pixi-v7/src/Spine.ts b/spine-ts/spine-pixi-v7/src/Spine.ts index 68f446c98..eded67945 100644 --- a/spine-ts/spine-pixi-v7/src/Spine.ts +++ b/spine-ts/spine-pixi-v7/src/Spine.ts @@ -40,7 +40,7 @@ import { Skeleton, SkeletonBinary, SkeletonClipping, - type SkeletonData, + SkeletonData, SkeletonJson, Skin, Utils, @@ -329,10 +329,12 @@ export class Spine extends Container { private _boundsSpineID = -1; private _boundsSpineDirty = true; - constructor (options: SpineOptions | SpineFromOptions) { + constructor (options: SkeletonData | SpineOptions | SpineFromOptions) { super(); - if ("skeleton" in options) + if (options instanceof SkeletonData) + options = { skeletonData: options }; + else if ("skeleton" in options) options = new.target.createOptions(options); const { autoUpdate = true, boundsProvider, darkTint, skeletonData } = options; diff --git a/spine-ts/spine-pixi-v7/src/SpineDebugRenderer.ts b/spine-ts/spine-pixi-v7/src/SpineDebugRenderer.ts index cb69ab497..d1deb0bb9 100644 --- a/spine-ts/spine-pixi-v7/src/SpineDebugRenderer.ts +++ b/spine-ts/spine-pixi-v7/src/SpineDebugRenderer.ts @@ -27,12 +27,12 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +import type { AnimationStateListener } from "@esotericsoftware/spine-core"; +import { ClippingAttachment, MeshAttachment, PathAttachment, RegionAttachment, SkeletonBounds } from "@esotericsoftware/spine-core"; import { Container } from "@pixi/display"; import { Graphics } from "@pixi/graphics"; import { Text } from "@pixi/text"; import type { Spine } from "./Spine.js"; -import type { AnimationStateListener } from "@esotericsoftware/spine-core"; -import { ClippingAttachment, MeshAttachment, PathAttachment, RegionAttachment, SkeletonBounds } from "@esotericsoftware/spine-core"; /** * Make a class that extends from this interface to create your own debug renderer. @@ -159,9 +159,10 @@ export class SpineDebugRenderer implements ISpineDebugRenderer { debugDisplayObjects.parentDebugContainer.zIndex = 9999999; // Disable screen reader and mouse input on debug objects. + // biome-ignore lint/suspicious/noExplicitAny: this prop is available in later versions (debugDisplayObjects.parentDebugContainer as any).accessibleChildren = false; - (debugDisplayObjects.parentDebugContainer as any).eventMode = "none"; - (debugDisplayObjects.parentDebugContainer as any).interactiveChildren = false; + (debugDisplayObjects.parentDebugContainer).eventMode = "none"; + (debugDisplayObjects.parentDebugContainer).interactiveChildren = false; spine.addChild(debugDisplayObjects.parentDebugContainer); diff --git a/spine-ts/spine-pixi-v7/src/SpineTexture.ts b/spine-ts/spine-pixi-v7/src/SpineTexture.ts index ef924ec62..23bedc49c 100644 --- a/spine-ts/spine-pixi-v7/src/SpineTexture.ts +++ b/spine-ts/spine-pixi-v7/src/SpineTexture.ts @@ -28,15 +28,15 @@ *****************************************************************************/ import { BlendMode, Texture, TextureFilter, TextureWrap } from "@esotericsoftware/spine-core"; -import type { BaseTexture as PixiBaseTexture, BaseImageResource } from "@pixi/core"; -import { Texture as PixiTexture, SCALE_MODES, MIPMAP_MODES, WRAP_MODES, BLEND_MODES } from "@pixi/core"; +import type { BaseImageResource, BaseTexture as PixiBaseTexture } from "@pixi/core"; +import { BLEND_MODES, MIPMAP_MODES, Texture as PixiTexture, SCALE_MODES, WRAP_MODES } from "@pixi/core"; export class SpineTexture extends Texture { private static textureMap: Map = new Map(); public static from (texture: PixiBaseTexture): SpineTexture { if (SpineTexture.textureMap.has(texture)) { - return SpineTexture.textureMap.get(texture)!; + return SpineTexture.textureMap.get(texture) as SpineTexture; } return new SpineTexture(texture); } @@ -45,7 +45,7 @@ export class SpineTexture extends Texture { private constructor (image: PixiBaseTexture) { // Todo: maybe add error handling if you feed a video texture to spine? - super((image.resource as BaseImageResource).source as any); + super((image.resource as BaseImageResource).source); this.texture = PixiTexture.from(image); } diff --git a/spine-ts/spine-pixi-v7/src/assets/AtlasLoader.ts b/spine-ts/spine-pixi-v7/src/assets/AtlasLoader.ts index 7ff61ba14..ceda220f3 100644 --- a/spine-ts/spine-pixi-v7/src/assets/AtlasLoader.ts +++ b/spine-ts/spine-pixi-v7/src/assets/AtlasLoader.ts @@ -28,12 +28,11 @@ *****************************************************************************/ import { TextureAtlas } from "@esotericsoftware/spine-core"; -import { SpineTexture } from "../SpineTexture.js"; import type { AssetExtension, Loader, ResolvedAsset, UnresolvedAsset } from "@pixi/assets"; -import { Assets, copySearchParams } from "@pixi/assets"; -import { LoaderParserPriority, checkExtension } from "@pixi/assets"; +import { Assets, checkExtension, copySearchParams, LoaderParserPriority } from "@pixi/assets"; import type { Texture } from "@pixi/core"; -import { ALPHA_MODES, ExtensionType, settings, utils, BaseTexture, extensions } from "@pixi/core"; +import { ALPHA_MODES, BaseTexture, ExtensionType, extensions, settings, utils } from "@pixi/core"; +import { SpineTexture } from "../SpineTexture.js"; type RawAtlas = string; @@ -75,7 +74,7 @@ const spineTextureAtlasLoader: AssetExtension { - const isExtensionRight = checkExtension(options.src!, ".atlas"); + const isExtensionRight = checkExtension(options.src as string, ".atlas"); const isString = typeof asset === "string"; const isExplicitLoadParserSet = options.loadParser === loaderName; @@ -111,7 +110,7 @@ const spineTextureAtlasLoader: AssetExtension; diff --git a/spine-ts/spine-pixi-v7/src/assets/SkeletonLoader.ts b/spine-ts/spine-pixi-v7/src/assets/SkeletonLoader.ts index 46b6cd759..a8de3fff2 100644 --- a/spine-ts/spine-pixi-v7/src/assets/SkeletonLoader.ts +++ b/spine-ts/spine-pixi-v7/src/assets/SkeletonLoader.ts @@ -28,18 +28,21 @@ *****************************************************************************/ import type { AssetExtension, ResolvedAsset } from "@pixi/assets"; -import { LoaderParserPriority, checkExtension } from "@pixi/assets"; -import { ExtensionType, settings, extensions } from "@pixi/core"; +import { checkExtension, LoaderParserPriority } from "@pixi/assets"; +import { ExtensionType, extensions, settings } from "@pixi/core"; +// biome-ignore lint/suspicious/noExplicitAny: any until we have a schema type SkeletonJsonAsset = any; type SkeletonBinaryAsset = Uint8Array; const loaderName = "spineSkeletonLoader"; +// biome-ignore lint/suspicious/noExplicitAny: can receive any function isJson (resource: any): resource is SkeletonJsonAsset { return resource.hasOwnProperty("bones"); } +// biome-ignore lint/suspicious/noExplicitAny: can receive any function isBuffer (resource: any): resource is SkeletonBinaryAsset { return resource instanceof Uint8Array; } @@ -67,8 +70,8 @@ const spineLoaderExtension: AssetExtension { - const isJsonSpineModel = checkExtension(options.src!, ".json") && isJson(asset); - const isBinarySpineModel = checkExtension(options.src!, ".skel") && isBuffer(asset); + const isJsonSpineModel = checkExtension(options.src as string, ".json") && isJson(asset); + const isBinarySpineModel = checkExtension(options.src as string, ".skel") && isBuffer(asset); const isExplicitLoadParserSet = options.loadParser === loaderName; return Promise.resolve(isJsonSpineModel || isBinarySpineModel || isExplicitLoadParserSet); diff --git a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintBatchGeom.ts b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintBatchGeom.ts index 5b2c66fad..b4474a78b 100644 --- a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintBatchGeom.ts +++ b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintBatchGeom.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Geometry, Buffer, TYPES } from "@pixi/core"; +import { Buffer, Geometry, TYPES } from "@pixi/core"; /** * Geometry used to batch standard PIXI content (e.g. Mesh, Sprite, Graphics objects). diff --git a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintGeom.ts b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintGeom.ts index 097d5c1ad..cc528d1e8 100644 --- a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintGeom.ts +++ b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintGeom.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Geometry, Buffer, TYPES } from "@pixi/core"; +import { Buffer, Geometry, TYPES } from "@pixi/core"; /** * Geometry used to batch standard PIXI content (e.g. Mesh, Sprite, Graphics objects). diff --git a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMaterial.ts b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMaterial.ts index fddce1254..003c3a038 100644 --- a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMaterial.ts +++ b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMaterial.ts @@ -28,7 +28,7 @@ *****************************************************************************/ import type { ColorSource } from "@pixi/core"; -import { Shader, TextureMatrix, Color, Texture, Matrix, Program } from "@pixi/core"; +import { Color, Matrix, Program, Shader, Texture, TextureMatrix } from "@pixi/core"; const vertex = ` attribute vec2 aVertexPosition; @@ -163,7 +163,7 @@ export class DarkTintMaterial extends Shader { this._colorDirty = true; } public get tint (): ColorSource { - return this._tintColor.value!; + return this._tintColor.value as ColorSource; } public set darkTint (value: ColorSource) { @@ -176,7 +176,7 @@ export class DarkTintMaterial extends Shader { this._colorDirty = true; } public get darkTint (): ColorSource { - return this._darkTintColor.value!; + return this._darkTintColor.value as ColorSource; } public get tintValue (): number { diff --git a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMesh.ts b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMesh.ts index d5508b3db..8916fd47f 100644 --- a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMesh.ts +++ b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintMesh.ts @@ -27,7 +27,7 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import type { Texture, ColorSource, Renderer, BLEND_MODES } from "@pixi/core"; +import type { BLEND_MODES, ColorSource, Renderer, Texture } from "@pixi/core"; import { Mesh } from "@pixi/mesh"; import { DarkTintGeometry } from "./DarkTintGeom.js"; import { DarkTintMaterial } from "./DarkTintMaterial.js"; @@ -60,11 +60,11 @@ export class DarkTintMesh extends Mesh { } public set darkTint (value: ColorSource | null) { - (this.shader as unknown as DarkTintMaterial).darkTint = value!; + this.shader.darkTint = value as ColorSource; } public get darkTintValue (): number { - return (this.shader as unknown as DarkTintMaterial).darkTintValue; + return this.shader.darkTintValue; } // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintRenderer.ts b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintRenderer.ts index 40632d5be..2ed71ae1a 100644 --- a/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintRenderer.ts +++ b/spine-ts/spine-pixi-v7/src/darkTintMesh/DarkTintRenderer.ts @@ -27,10 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import type { IDarkTintElement } from "./DarkTintMesh.js"; -import { DarkTintBatchGeometry } from "./DarkTintBatchGeom.js"; import type { ExtensionMetadata, Renderer, ViewableBuffer } from "@pixi/core"; -import { extensions, BatchRenderer, ExtensionType, BatchShaderGenerator, Color } from "@pixi/core"; +import { BatchRenderer, BatchShaderGenerator, Color, ExtensionType, extensions } from "@pixi/core"; +import { DarkTintBatchGeometry } from "./DarkTintBatchGeom.js"; +import type { IDarkTintElement } from "./DarkTintMesh.js"; const vertex = ` precision highp float; diff --git a/spine-ts/spine-pixi-v7/src/index.ts b/spine-ts/spine-pixi-v7/src/index.ts index 4cfca0885..c44b555fa 100644 --- a/spine-ts/spine-pixi-v7/src/index.ts +++ b/spine-ts/spine-pixi-v7/src/index.ts @@ -1,18 +1,48 @@ -export * from './require-shim.js'; -export * from './Spine.js'; -export * from './SpineDebugRenderer.js'; -export * from './SpineTexture.js'; -export * from './SlotMesh.js'; -export * from './DarkSlotMesh.js'; +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated September 24, 2021. Replaces all prior versions. + * + * Copyright (c) 2013-2021, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +import './require-shim.js'; +import './assets/AtlasLoader.js'; // Side effects install the loaders into pixi +import './assets/SkeletonLoader.js'; // Side effects install the loaders into pixi + +export * from "@esotericsoftware/spine-core"; export * from './assets/AtlasLoader.js'; export * from './assets/SkeletonLoader.js'; +export * from './DarkSlotMesh.js'; export * from './darkTintMesh/DarkTintBatchGeom.js'; export * from './darkTintMesh/DarkTintGeom.js'; export * from './darkTintMesh/DarkTintMaterial.js'; export * from './darkTintMesh/DarkTintMesh.js'; export * from './darkTintMesh/DarkTintRenderer.js'; -export * from "@esotericsoftware/spine-core"; +export * from './SlotMesh.js'; +export * from './Spine.js'; +export * from './SpineDebugRenderer.js'; +export * from './SpineTexture.js'; -import './assets/AtlasLoader.js'; // Side effects install the loaders into pixi -import './assets/SkeletonLoader.js'; // Side effects install the loaders into pixi diff --git a/spine-ts/spine-pixi-v7/src/require-shim.ts b/spine-ts/spine-pixi-v7/src/require-shim.ts index 8e444ba5c..ea821b1e9 100644 --- a/spine-ts/spine-pixi-v7/src/require-shim.ts +++ b/spine-ts/spine-pixi-v7/src/require-shim.ts @@ -27,8 +27,10 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +// biome-ignore-all lint: ignore biome for this file + if (typeof window !== 'undefined' && (window as any).PIXI) { - let prevRequire = window.require; + const prevRequire = window.require; (window as any).require = (x: string) => { if (prevRequire) return prevRequire(x); else if (x.startsWith("@pixi/")) return (window as any).PIXI; diff --git a/spine-ts/spine-pixi-v8/src/BatchableSpineSlot.ts b/spine-ts/spine-pixi-v8/src/BatchableSpineSlot.ts index 76e1e9391..acf91b98a 100644 --- a/spine-ts/spine-pixi-v8/src/BatchableSpineSlot.ts +++ b/spine-ts/spine-pixi-v8/src/BatchableSpineSlot.ts @@ -27,9 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { AttachmentCacheData, Spine } from './Spine.js'; import type { Batch, Batcher, BLEND_MODES, DefaultBatchableMeshElement, Matrix, Texture, Topology } from 'pixi.js'; +import type { AttachmentCacheData, ClippedData, Spine } from './Spine.js'; export class BatchableSpineSlot implements DefaultBatchableMeshElement { indexOffset = 0; @@ -112,13 +112,13 @@ export class BatchableSpineSlot implements DefaultBatchableMeshElement { this.data = data; if (data.clipped) { - const clippedData = data.clippedData; + const clippedData = data.clippedData as ClippedData; - this.indexSize = clippedData!.indicesCount; - this.attributeSize = clippedData!.vertexCount; - this.positions = clippedData!.vertices; - this.indices = clippedData!.indices; - this.uvs = clippedData!.uvs; + this.indexSize = clippedData.indicesCount; + this.attributeSize = clippedData.vertexCount; + this.positions = clippedData.vertices; + this.indices = clippedData.indices; + this.uvs = clippedData.uvs; } else { this.indexSize = data.indices.length; diff --git a/spine-ts/spine-pixi-v8/src/Spine.ts b/spine-ts/spine-pixi-v8/src/Spine.ts index 127da20e9..212b171ab 100644 --- a/spine-ts/spine-pixi-v8/src/Spine.ts +++ b/spine-ts/spine-pixi-v8/src/Spine.ts @@ -43,7 +43,7 @@ import { SkeletonBinary, SkeletonBounds, SkeletonClipping, - type SkeletonData, + SkeletonData, SkeletonJson, Skin, type Slot, @@ -261,6 +261,14 @@ export interface SpineEvents { start: [trackEntry: TrackEntry]; } +export interface ClippedData { + vertices: Float32Array; + uvs: Float32Array; + indices: Uint16Array; + vertexCount: number; + indicesCount: number; +} + export interface AttachmentCacheData { id: string; clipped: boolean; @@ -272,13 +280,7 @@ export interface AttachmentCacheData { darkTint: boolean; skipRender: boolean; texture: Texture; - clippedData?: { - vertices: Float32Array; - uvs: Float32Array; - indices: Uint16Array; - vertexCount: number; - indicesCount: number; - }; + clippedData?: ClippedData; } interface SlotsToClipping { @@ -385,10 +387,12 @@ export class Spine extends ViewContainer { } private hasNeverUpdated = true; - constructor (options: SpineOptions | SpineFromOptions) { + constructor (options: SkeletonData | SpineOptions | SpineFromOptions) { super({}); - if ("skeleton" in options) + if (options instanceof SkeletonData) + options = { skeletonData: options }; + else if ("skeleton" in options) options = new.target.createOptions(options); this.allowChildren = true; @@ -579,7 +583,7 @@ export class Spine extends ViewContainer { const clippingAttachment = slotClipping.pose.attachment as ClippingAttachment; // create the pixi mask, only the first time and if the clipped slot is the first one clipped by this currentClippingSlot - let mask = currentClippingSlot.mask as Graphics; + let mask = currentClippingSlot.mask; if (!mask) { mask = maskPool.obtain(); currentClippingSlot.mask = mask; @@ -1030,11 +1034,11 @@ export class Spine extends ViewContainer { Ticker.shared.remove(this.internalUpdate, this); this.state.clearListeners(); this.debug = undefined; - this.skeleton = null as any; - this.state = null as any; - (this._slotsObject as any) = null; + (this.skeleton as unknown) = null; + (this.state as unknown) = null; + (this._slotsObject as unknown) = null; + (this.attachmentCacheData as unknown) = null; this._lastAttachments.length = 0; - this.attachmentCacheData = null as any; } /** Converts a point from the skeleton coordinate system to the Pixi world coordinate system. */ diff --git a/spine-ts/spine-pixi-v8/src/SpineDebugRenderer.ts b/spine-ts/spine-pixi-v8/src/SpineDebugRenderer.ts index 547430e89..a8a545f8c 100644 --- a/spine-ts/spine-pixi-v8/src/SpineDebugRenderer.ts +++ b/spine-ts/spine-pixi-v8/src/SpineDebugRenderer.ts @@ -27,8 +27,8 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Container, Graphics, Text } from 'pixi.js'; -import { Spine } from './Spine.js'; + +import type { AnimationStateListener } from '@esotericsoftware/spine-core'; import { ClippingAttachment, MeshAttachment, @@ -36,8 +36,8 @@ import { RegionAttachment, SkeletonBounds } from '@esotericsoftware/spine-core'; - -import type { AnimationStateListener } from '@esotericsoftware/spine-core'; +import { Container, Graphics, Text } from 'pixi.js'; +import type { Spine } from './Spine.js'; /** * Make a class that extends from this interface to create your own debug renderer. @@ -171,12 +171,12 @@ export class SpineDebugRenderer implements ISpineDebugRenderer { debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.pathsLine); debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.eventText); - (debugDisplayObjects.parentDebugContainer as any).zIndex = 9999999; + debugDisplayObjects.parentDebugContainer.zIndex = 9999999; // Disable screen reader and mouse input on debug objects. - (debugDisplayObjects.parentDebugContainer as any).accessibleChildren = false; - (debugDisplayObjects.parentDebugContainer as any).eventMode = 'none'; - (debugDisplayObjects.parentDebugContainer as any).interactiveChildren = false; + debugDisplayObjects.parentDebugContainer.accessibleChildren = false; + debugDisplayObjects.parentDebugContainer.eventMode = 'none'; + debugDisplayObjects.parentDebugContainer.interactiveChildren = false; spine.addChild(debugDisplayObjects.parentDebugContainer); diff --git a/spine-ts/spine-pixi-v8/src/SpinePipe.ts b/spine-ts/spine-pixi-v8/src/SpinePipe.ts index bfa244e4d..2f4400c92 100644 --- a/spine-ts/spine-pixi-v8/src/SpinePipe.ts +++ b/spine-ts/spine-pixi-v8/src/SpinePipe.ts @@ -150,6 +150,7 @@ export class SpinePipe implements RenderPipe { if (!skipRender) { container.includeInBuild = true; // See https://github.com/pixijs/pixijs/blob/b4c050a791fe65e979e467c9cba2bda0c01a1c35/src/scene/container/utils/collectAllRenderables.ts#L28 + // biome-ignore lint/style/noNonNullAssertion: it was in pixi code container.collectRenderables(instructionSet, this.renderer, null!); } @@ -185,13 +186,13 @@ export class SpinePipe implements RenderPipe { } destroyRenderable (spine: Spine) { - this.gpuSpineData[spine.uid] = null as any; + (this.gpuSpineData[spine.uid] as unknown) = null; spine.off('destroyed', this._destroyRenderableBound); } destroy () { - this.gpuSpineData = null as any; - this.renderer = null as any; + (this.gpuSpineData as unknown) = null; + (this.renderer as unknown) = null; } private _getSpineData (spine: Spine): GpuSpineDataElement { diff --git a/spine-ts/spine-pixi-v8/src/SpineTexture.ts b/spine-ts/spine-pixi-v8/src/SpineTexture.ts index 466161128..70a4c3102 100644 --- a/spine-ts/spine-pixi-v8/src/SpineTexture.ts +++ b/spine-ts/spine-pixi-v8/src/SpineTexture.ts @@ -27,10 +27,9 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Texture as PixiTexture } from 'pixi.js'; import { BlendMode, Texture, TextureFilter, TextureWrap } from '@esotericsoftware/spine-core'; - import type { BLEND_MODES, SCALE_MODE, TextureSource, WRAP_MODE } from 'pixi.js'; +import { Texture as PixiTexture } from 'pixi.js'; export class SpineTexture extends Texture { private static readonly textureMap: Map = new Map(); diff --git a/spine-ts/spine-pixi-v8/src/assets/AtlasLoader.ts b/spine-ts/spine-pixi-v8/src/assets/AtlasLoader.ts index 148e8d281..08ecfe230 100644 --- a/spine-ts/spine-pixi-v8/src/assets/AtlasLoader.ts +++ b/spine-ts/spine-pixi-v8/src/assets/AtlasLoader.ts @@ -120,7 +120,7 @@ const spineTextureAtlasLoader: AssetExtension[] = []; + const textureLoadingPromises: Promise[] = []; // fill the pages for (const page of retval.pages) { @@ -161,6 +161,7 @@ extensions.add(spineTextureAtlasLoader); export interface ISpineAtlasMetadata { // If you are downloading an .atlas file, this metadata will go to the Texture loader + // biome-ignore lint/suspicious/noExplicitAny: user can pass any imageMetadata?: any; // If you already have atlas pages loaded as pixi textures // and want to use that to create the atlas, you can pass them here diff --git a/spine-ts/spine-pixi-v8/src/assets/SkeletonLoader.ts b/spine-ts/spine-pixi-v8/src/assets/SkeletonLoader.ts index b6a74cc44..50af951f2 100644 --- a/spine-ts/spine-pixi-v8/src/assets/SkeletonLoader.ts +++ b/spine-ts/spine-pixi-v8/src/assets/SkeletonLoader.ts @@ -37,15 +37,18 @@ import { type ResolvedAsset } from 'pixi.js'; +// biome-ignore lint/suspicious/noExplicitAny: can receive any type SkeletonJsonAsset = any; type SkeletonBinaryAsset = Uint8Array; const loaderName = "spineSkeletonLoader"; +// biome-ignore lint/suspicious/noExplicitAny: can receive any function isJson (resource: any): resource is SkeletonJsonAsset { return Object.prototype.hasOwnProperty.call(resource, 'bones'); } +// biome-ignore lint/suspicious/noExplicitAny: can receive any function isBuffer (resource: any): resource is SkeletonBinaryAsset { return resource instanceof Uint8Array; } @@ -74,8 +77,8 @@ const spineLoaderExtension: AssetExtension { - const isJsonSpineModel = checkExtension(options.src!, '.json') && isJson(asset); - const isBinarySpineModel = checkExtension(options.src!, '.skel') && isBuffer(asset); + const isJsonSpineModel = checkExtension(options.src as string, '.json') && isJson(asset); + const isBinarySpineModel = checkExtension(options.src as string, '.skel') && isBuffer(asset); const isExplicitLoadParserSet = options.parser === loaderName || options.loadParser === loaderName; return Promise.resolve(isJsonSpineModel || isBinarySpineModel || isExplicitLoadParserSet); diff --git a/spine-ts/spine-pixi-v8/src/darktint/DarkTintBatcher.ts b/spine-ts/spine-pixi-v8/src/darktint/DarkTintBatcher.ts index 029e614db..e15554371 100644 --- a/spine-ts/spine-pixi-v8/src/darktint/DarkTintBatcher.ts +++ b/spine-ts/spine-pixi-v8/src/darktint/DarkTintBatcher.ts @@ -30,11 +30,11 @@ import { Batcher, Color, - DefaultBatchableMeshElement, - DefaultBatchableQuadElement, - extensions, + type DefaultBatchableMeshElement, + type DefaultBatchableQuadElement, ExtensionType, - Shader + extensions, + type Shader } from 'pixi.js'; import { DarkTintBatchGeometry } from './DarkTintBatchGeometry.js'; import { DarkTintShader } from './DarkTintShader.js'; diff --git a/spine-ts/spine-pixi-v8/src/index.ts b/spine-ts/spine-pixi-v8/src/index.ts index a12fa1f0a..02bf955a4 100644 --- a/spine-ts/spine-pixi-v8/src/index.ts +++ b/spine-ts/spine-pixi-v8/src/index.ts @@ -33,6 +33,7 @@ import './assets/SkeletonLoader.js'; // Side effects install the loaders into pi import './darktint/DarkTintBatcher.js'; // Side effects install the batcher into pixi import './SpinePipe.js'; +export * from '@esotericsoftware/spine-core'; export * from './assets/AtlasLoader.js'; export * from './assets/SkeletonLoader.js'; export * from './require-shim.js'; @@ -40,4 +41,3 @@ export * from './Spine.js'; export * from './SpineDebugRenderer.js'; export * from './SpinePipe.js'; export * from './SpineTexture.js'; -export * from '@esotericsoftware/spine-core'; diff --git a/spine-ts/spine-pixi-v8/src/require-shim.ts b/spine-ts/spine-pixi-v8/src/require-shim.ts index ea8c341b0..c54afc6a1 100644 --- a/spine-ts/spine-pixi-v8/src/require-shim.ts +++ b/spine-ts/spine-pixi-v8/src/require-shim.ts @@ -27,6 +27,8 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +// biome-ignore-all lint: ignore biome for this file + if (typeof window !== 'undefined' && (window as any).PIXI) { const prevRequire = window.require; (window as any).require = (x: string) => { diff --git a/spine-ts/spine-player/src/Player.ts b/spine-ts/spine-player/src/Player.ts index fb2cc68eb..4ae81c439 100644 --- a/spine-ts/spine-player/src/Player.ts +++ b/spine-ts/spine-player/src/Player.ts @@ -27,22 +27,16 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation, AnimationState, AnimationStateData, AtlasAttachmentLoader, Bone, Color, Disposable, Downloader, MathUtils, MixBlend, MixDirection, Physics, Skeleton, SkeletonBinary, SkeletonData, SkeletonJson, StringMap, TextureAtlas, TextureFilter, TimeKeeper, TrackEntry, Vector2 } from "@esotericsoftware/spine-core" -import { AssetManager, GLTexture, Input, LoadingScreen, ManagedWebGLRenderingContext, ResizeMode, SceneRenderer, Vector3 } from "@esotericsoftware/spine-webgl" +import { type Animation, AnimationState, AnimationStateData, AtlasAttachmentLoader, type Bone, Color, type Disposable, type Downloader, MathUtils, MixBlend, MixDirection, Physics, Skeleton, SkeletonBinary, type SkeletonData, SkeletonJson, type StringMap, type TextureAtlas, TextureFilter, TimeKeeper, type TrackEntry, Vector2 } from "@esotericsoftware/spine-core" +import { AssetManager, type GLTexture, Input, LoadingScreen, ManagedWebGLRenderingContext, ResizeMode, SceneRenderer, Vector3 } from "@esotericsoftware/spine-webgl" export interface SpinePlayerConfig { /* The URL of the skeleton JSON (.json) or binary (.skel) file */ skeleton?: string; - /* @deprecated Use skeleton instead. The URL of the skeleton JSON file (.json). Undefined if binaryUrl is given. */ - jsonUrl?: string - /* Optional: The name of a field in the JSON that holds the skeleton data. Default: none */ jsonField?: string - /* @deprecated Use skeleton instead. The URL of the skeleton binary file (.skel). Undefined if jsonUrl is given. */ - binaryUrl?: string - /* The scale when loading the skeleton data. Default: 1 */ scale?: number @@ -245,12 +239,12 @@ export class SpinePlayer implements Disposable { private input?: Input; constructor (parent: HTMLElement | string, private config: SpinePlayerConfig) { - let parentDom = typeof parent === "string" ? document.getElementById(parent) : parent; - if (parentDom == null) throw new Error("SpinePlayer parent not found: " + parent); + const parentDom = typeof parent === "string" ? document.getElementById(parent) : parent; + if (parentDom == null) throw new Error(`SpinePlayer parent not found: ${parent}`); this.parent = parentDom; if (config.showControls === void 0) config.showControls = true; - let controls = config.showControls ? /*html*/` + const controls = config.showControls ? /*html*/`
@@ -287,8 +281,8 @@ export class SpinePlayer implements Disposable { this.loadingScreen?.dispose(); this.assetManager?.dispose(); this.context?.dispose(); - for (var i = 0; i < this.eventListeners.length; i++) { - var eventListener = this.eventListeners[i]; + for (let i = 0; i < this.eventListeners.length; i++) { + const eventListener = this.eventListeners[i]; eventListener.target.removeEventListener(eventListener.event, eventListener.func); } this.input?.dispose(); @@ -308,12 +302,10 @@ export class SpinePlayer implements Disposable { private validateConfig (config: SpinePlayerConfig) { if (!config) throw new Error("A configuration object must be passed to to new SpinePlayer()."); if ((config as any).skelUrl) config.skeleton = (config as any).skelUrl; - if (!config.skeleton && !config.jsonUrl && !config.binaryUrl) throw new Error("A URL must be specified for the skeleton JSON or binary file."); + if (!config.skeleton) throw new Error("A URL must be specified for the skeleton JSON or binary file."); if (!config.scale) config.scale = 1; if (!config.atlas && !config.atlasUrl) throw new Error("A URL must be specified for the atlas file."); - if (config.jsonUrl && !config.skeleton) config.skeleton = config.jsonUrl; - if (config.binaryUrl && !config.skeleton) config.skeleton = config.binaryUrl; if (config.atlasUrl && !config.atlas) config.atlas = config.atlasUrl; if (!config.backgroundColor) config.backgroundColor = config.alpha ? "00000000" : "000000"; @@ -334,9 +326,9 @@ export class SpinePlayer implements Disposable { regions: false }; if (config.animations && config.animation && config.animations.indexOf(config.animation) < 0) - throw new Error("Animation '" + config.animation + "' is not in the config animation list: " + toString(config.animations)); + throw new Error(`Animation '${config.animation}' is not in the config animation list: ${print(config.animations)}`); if (config.skins && config.skin && config.skins.indexOf(config.skin) < 0) - throw new Error("Default skin '" + config.skin + "' is not in the config skins list: " + toString(config.skins)); + throw new Error(`Default skin '${config.skin}' is not in the config skins list: ${print(config.skins)}`); if (!config.viewport) config.viewport = {} as any; if (!config.viewport!.animations) config.viewport!.animations = {}; if (config.viewport!.debugRender === void 0) config.viewport!.debugRender = false; @@ -347,12 +339,12 @@ export class SpinePlayer implements Disposable { } private initialize (): HTMLElement | null { - let config = this.config; - let dom = this.dom; + const config = this.config; + const dom = this.dom; if (!config.alpha) { // Prevents a flash before the first frame is drawn. - let hex = config.backgroundColor!; - this.dom.style.backgroundColor = (hex.charAt(0) == '#' ? hex : "#" + hex).substr(0, 7); + const hex = config.backgroundColor!; + this.dom.style.backgroundColor = (hex.charAt(0) === '#' ? hex : `#${hex}`).substr(0, 7); } try { @@ -371,7 +363,7 @@ export class SpinePlayer implements Disposable { // Load the assets. this.assetManager = new AssetManager(this.context, "", config.downloader); if (config.rawDataURIs) { - for (let path in config.rawDataURIs) + for (const path in config.rawDataURIs) this.assetManager.setRawDataURI(path, config.rawDataURIs[path]); } if (config.skeleton!.endsWith(".json")) @@ -386,23 +378,23 @@ export class SpinePlayer implements Disposable { this.bgFullscreen.setFromString(config.fullScreenBackgroundColor!); if (config.showControls) { this.playerControls = dom.children[1] as HTMLElement; - let controls = this.playerControls.children; - let timeline = controls[0] as HTMLElement; - let buttons = controls[1].children; + const controls = this.playerControls.children; + const timeline = controls[0] as HTMLElement; + const buttons = controls[1].children; this.playButton = buttons[0] as HTMLElement; - let speedButton = buttons[2] as HTMLElement; + const speedButton = buttons[2] as HTMLElement; this.animationButton = buttons[3] as HTMLElement; this.skinButton = buttons[4] as HTMLElement; - let settingsButton = buttons[5] as HTMLElement; - let fullscreenButton = buttons[6] as HTMLElement; - let logoButton = buttons[7] as HTMLElement; + const settingsButton = buttons[5] as HTMLElement; + const fullscreenButton = buttons[6] as HTMLElement; + const logoButton = buttons[7] as HTMLElement; this.timelineSlider = new Slider(); timeline.appendChild(this.timelineSlider.create()); this.timelineSlider.change = (percentage) => { this.pause(); - let animationDuration = this.animationState!.getCurrent(0)!.animation!.duration; - let time = animationDuration * percentage; + const animationDuration = this.animationState!.getCurrent(0)!.animation!.duration; + const time = animationDuration * percentage; this.animationState!.update(time - this.playTime); this.animationState!.apply(this.skeleton!); this.skeleton!.update(time - this.playTime); @@ -420,11 +412,11 @@ export class SpinePlayer implements Disposable { let oldStyleWidth = this.canvas.style.width, oldStyleHeight = this.canvas.style.height; let isFullscreen = false; fullscreenButton.onclick = () => { - let fullscreenChanged = () => { + const fullscreenChanged = () => { isFullscreen = !isFullscreen; if (!isFullscreen) { - this.canvas!.style.width = oldWidth + "px"; - this.canvas!.style.height = oldHeight + "px"; + this.canvas!.style.width = `${oldWidth}px`; + this.canvas!.style.height = `${oldHeight}px`; this.drawFrame(false); // Got to reset the style to whatever the user set after the next layouting. requestAnimationFrame(() => { @@ -434,11 +426,11 @@ export class SpinePlayer implements Disposable { } }; - let player = dom as any; + const player = dom as any; player.onfullscreenchange = fullscreenChanged; player.onwebkitfullscreenchange = fullscreenChanged; - let doc = document as any; + const doc = document as any; if (doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement) { if (doc.exitFullscreen) doc.exitFullscreen(); else if (doc.mozCancelFullScreen) doc.mozCancelFullScreen(); @@ -465,18 +457,18 @@ export class SpinePlayer implements Disposable { if (this.error) return; if (this.assetManager!.hasErrors()) - this.showError("Error: Assets could not be loaded.\n" + toString(this.assetManager!.getErrors())); + this.showError(`Error: Assets could not be loaded.\n${print(this.assetManager!.getErrors())}`); - let config = this.config; + const config = this.config; // Configure filtering, don't use mipmaps in WebGL1 if the atlas page is non-POT - let atlas = this.assetManager!.require(config.atlas!) as TextureAtlas; - let gl = this.context!.gl, anisotropic = gl.getExtension("EXT_texture_filter_anisotropic"); - let isWebGL1 = gl.getParameter(gl.VERSION).indexOf("WebGL 1.0") != -1; - for (let page of atlas.pages) { + const atlas = this.assetManager!.require(config.atlas!) as TextureAtlas; + const gl = this.context!.gl, anisotropic = gl.getExtension("EXT_texture_filter_anisotropic"); + const isWebGL1 = gl.getParameter(gl.VERSION).indexOf("WebGL 1.0") !== -1; + for (const page of atlas.pages) { let minFilter = page.minFilter; - var useMipMaps: boolean = config.mipmaps!; - var isPOT = MathUtils.isPowerOfTwo(page.width) && MathUtils.isPowerOfTwo(page.height); + let useMipMaps: boolean = config.mipmaps!; + const isPOT = MathUtils.isPowerOfTwo(page.width) && MathUtils.isPowerOfTwo(page.height); if (isWebGL1 && !isPOT) useMipMaps = false; if (useMipMaps) { @@ -487,7 +479,7 @@ export class SpinePlayer implements Disposable { minFilter = TextureFilter.Linear; // Don't use mipmaps without anisotropic. page.texture!.setFilters(minFilter, TextureFilter.Nearest); } - if (minFilter != TextureFilter.Nearest && minFilter != TextureFilter.Linear) (page.texture as GLTexture).update(true); + if (minFilter !== TextureFilter.Nearest && minFilter !== TextureFilter.Linear) (page.texture as GLTexture).update(true); } // Load skeleton data. @@ -499,7 +491,7 @@ export class SpinePlayer implements Disposable { if (!data) throw new Error("Empty JSON data."); if (config.jsonField) { data = data[config.jsonField]; - if (!data) throw new Error("JSON field does not exist: " + config.jsonField); + if (!data) throw new Error(`JSON field does not exist: ${config.jsonField}`); } loader = new SkeletonJson(attachmentLoader); } else { @@ -513,7 +505,7 @@ export class SpinePlayer implements Disposable { return; } this.skeleton = new Skeleton(skeletonData); - let stateData = new AnimationStateData(skeletonData); + const stateData = new AnimationStateData(skeletonData); stateData.defaultMix = config.defaultMix!; this.animationState = new AnimationState(stateData); @@ -560,8 +552,8 @@ export class SpinePlayer implements Disposable { if (config.showControls) { // Hide skin and animation if there's only the default skin / no animation - if (skeletonData.skins.length == 1 || (config.skins && config.skins.length == 1)) this.skinButton!.classList.add("spine-player-hidden"); - if (skeletonData.animations.length == 1 || (config.animations && config.animations.length == 1)) this.animationButton!.classList.add("spine-player-hidden"); + if (skeletonData.skins.length === 1 || (config.skins && config.skins.length === 1)) this.skinButton!.classList.add("spine-player-hidden"); + if (skeletonData.animations.length === 1 || (config.animations && config.animations.length === 1)) this.animationButton!.classList.add("spine-player-hidden"); } if (config.success) config.success(this); @@ -590,30 +582,30 @@ export class SpinePlayer implements Disposable { } private setupInput () { - let config = this.config; - let controlBones = config.controlBones!; + const config = this.config; + const controlBones = config.controlBones!; if (!controlBones.length && !config.showControls) return; - let selectedBones = this.selectedBones = new Array(controlBones.length); - let canvas = this.canvas!; + const selectedBones = this.selectedBones = new Array(controlBones.length); + const canvas = this.canvas!; let target: Bone | null = null; - let offset = new Vector2(); - let coords = new Vector3(); - let mouse = new Vector3(); - let position = new Vector2(); - let skeleton = this.skeleton!; - let renderer = this.sceneRenderer!; + const offset = new Vector2(); + const coords = new Vector3(); + const mouse = new Vector3(); + const position = new Vector2(); + const skeleton = this.skeleton!; + const renderer = this.sceneRenderer!; if (config.interactive) { - let closest = function (x: number, y: number): Bone | null { + const closest = (x: number, y: number): Bone | null => { mouse.set(x, canvas.clientHeight - y, 0) offset.x = offset.y = 0; let bestDistance = 24, index = 0; let best: Bone | null = null; for (let i = 0; i < controlBones.length; i++) { selectedBones[i] = null; - let bone = skeleton.findBone(controlBones[i]); + const bone = skeleton.findBone(controlBones[i]); if (!bone) continue; - let distance = renderer.camera.worldToScreen( + const distance = renderer.camera.worldToScreen( coords.set(bone.applied.worldX, bone.applied.worldY, 0), canvas.clientWidth, canvas.clientHeight).distance(mouse); if (distance < bestDistance) { @@ -668,27 +660,27 @@ export class SpinePlayer implements Disposable { }); this.addEventListener(document, "touchmove", (ev: UIEvent) => { if (ev instanceof TouchEvent) { - let touches = ev.changedTouches; + const touches = ev.changedTouches; if (touches.length) { - let touch = touches[0]; + const touch = touches[0]; handleHover(touch.clientX, touch.clientY); } } }); - let overlap = (mouseX: number, mouseY: number, rect: DOMRect | ClientRect): boolean => { - let x = mouseX - rect.left, y = mouseY - rect.top; + const overlap = (mouseX: number, mouseY: number, rect: DOMRect | ClientRect): boolean => { + const x = mouseX - rect.left, y = mouseY - rect.top; return x >= 0 && x <= rect.width && y >= 0 && y <= rect.height; } let mouseOverControls = true, mouseOverCanvas = false; - let handleHover = (mouseX: number, mouseY: number) => { - let popup = findWithClass(this.dom, "spine-player-popup"); + const handleHover = (mouseX: number, mouseY: number) => { + const popup = findWithClass(this.dom, "spine-player-popup"); mouseOverControls = overlap(mouseX, mouseY, this.playerControls!.getBoundingClientRect()); mouseOverCanvas = overlap(mouseX, mouseY, canvas.getBoundingClientRect()); clearTimeout(this.cancelId); - let hide = !popup && !mouseOverControls && !mouseOverCanvas && !this.paused; + const hide = !popup && !mouseOverControls && !mouseOverCanvas && !this.paused; if (hide) this.playerControls!.classList.add("spine-player-controls-hidden"); else @@ -704,7 +696,7 @@ export class SpinePlayer implements Disposable { play () { this.paused = false; - let config = this.config; + const config = this.config; if (config.showControls) { this.cancelId = setTimeout(() => { if (!this.paused) this.playerControls!.classList.add("spine-player-controls-hidden"); @@ -747,17 +739,17 @@ export class SpinePlayer implements Disposable { /* Sets the viewport for the specified animation. */ setViewport (animation: string | Animation): Animation { - if (typeof animation == "string") { - let foundAnimation = this.skeleton!.data.findAnimation(animation); - if (!foundAnimation) throw new Error("Animation not found: " + animation); + if (typeof animation === "string") { + const foundAnimation = this.skeleton!.data.findAnimation(animation); + if (!foundAnimation) throw new Error(`Animation not found: ${animation}`); animation = foundAnimation; } this.previousViewport = this.currentViewport; // Determine the base viewport. - let globalViewport = this.config.viewport!; - let viewport = this.currentViewport = { + const globalViewport = this.config.viewport!; + const viewport = this.currentViewport = { clip: globalViewport.clip, padLeft: globalViewport.padLeft !== void 0 ? globalViewport.padLeft : "10%", padRight: globalViewport.padRight !== void 0 ? globalViewport.padRight : "10%", @@ -773,7 +765,7 @@ export class SpinePlayer implements Disposable { this.calculateAnimationViewport(animation, viewport); // Override with the animation specific viewport for the final result. - let userAnimViewport = this.config.viewport!.animations![animation.name]; + const userAnimViewport = this.config.viewport!.animations![animation.name]; if (userAnimViewport) { if (userAnimViewport.x !== void 0 && userAnimViewport.y !== void 0 && userAnimViewport.width && userAnimViewport.height) { viewport.x = userAnimViewport.x; @@ -809,7 +801,7 @@ export class SpinePlayer implements Disposable { let steps = 100, stepTime = animation.duration ? animation.duration / steps : 0, time = 0; let minX = 100000000, maxX = -100000000, minY = 100000000, maxY = -100000000; - let offset = new Vector2(), size = new Vector2(); + const offset = new Vector2(), size = new Vector2(); const tempArray = new Array(2); for (let i = 0; i < steps; i++, time += stepTime) { @@ -817,13 +809,13 @@ export class SpinePlayer implements Disposable { this.skeleton!.updateWorldTransform(Physics.update); this.skeleton!.getBounds(offset, size, tempArray, this.sceneRenderer!.skeletonRenderer.getSkeletonClipping()); - if (!isNaN(offset.x) && !isNaN(offset.y) && !isNaN(size.x) && !isNaN(size.y)) { + if (!Number.isNaN(offset.x) && !Number.isNaN(offset.y) && !Number.isNaN(size.x) && !Number.isNaN(size.y)) { minX = Math.min(offset.x, minX); maxX = Math.max(offset.x + size.x, maxX); minY = Math.min(offset.y, minY); maxY = Math.max(offset.y + size.y, maxY); } else - this.showError("Animation bounds are invalid: " + animation.name); + this.showError(`Animation bounds are invalid: ${animation.name}`); } viewport.x = minX; @@ -838,20 +830,20 @@ export class SpinePlayer implements Disposable { if (this.disposed) return; if (requestNextFrame && !this.stopRequestAnimationFrame) requestAnimationFrame(() => this.drawFrame()); - let doc = document as any; - let isFullscreen = doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement; - let bg = isFullscreen ? this.bgFullscreen : this.bg; + const doc = document as any; + const isFullscreen = doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement; + const bg = isFullscreen ? this.bgFullscreen : this.bg; this.time.update(); - let delta = this.time.delta; + const delta = this.time.delta; // Load the skeleton if the assets are ready. - let loading = !this.assetManager!.isLoadingComplete(); + const loading = !this.assetManager!.isLoadingComplete(); if (!this.skeleton && !loading) this.loadSkeleton(); - let skeleton = this.skeleton!; - let config = this.config!; + const skeleton = this.skeleton!; + const config = this.config!; if (skeleton) { - let playDelta = this.paused ? 0 : delta * this.speed; + const playDelta = this.paused ? 0 : delta * this.speed; if (config.frame) config.frame(this, playDelta); // Update animation time and pose the skeleton. @@ -866,10 +858,10 @@ export class SpinePlayer implements Disposable { if (config.showControls) { this.playTime += playDelta; - let entry = this.animationState!.getCurrent(0); + const entry = this.animationState!.getCurrent(0); if (entry) { - let duration = entry.animation!.duration; - while (this.playTime >= duration && duration != 0) + const duration = entry.animation!.duration; + while (this.playTime >= duration && duration !== 0) this.playTime -= duration; this.playTime = Math.max(0, Math.min(this.playTime, duration)); this.timelineSlider!.setValue(this.playTime / duration); @@ -878,19 +870,19 @@ export class SpinePlayer implements Disposable { } // Determine the viewport. - let viewport = this.viewport; + const viewport = this.viewport; viewport.x = this.currentViewport.x - (this.currentViewport.padLeft as number); viewport.y = this.currentViewport.y - (this.currentViewport.padBottom as number); viewport.width = this.currentViewport.width + (this.currentViewport.padLeft as number) + (this.currentViewport.padRight as number); viewport.height = this.currentViewport.height + (this.currentViewport.padBottom as number) + (this.currentViewport.padTop as number); if (this.previousViewport) { - let transitionAlpha = (performance.now() - this.viewportTransitionStart) / 1000 / config.viewport!.transitionTime!; + const transitionAlpha = (performance.now() - this.viewportTransitionStart) / 1000 / config.viewport!.transitionTime!; if (transitionAlpha < 1) { - let x = this.previousViewport.x - (this.previousViewport.padLeft as number); - let y = this.previousViewport.y - (this.previousViewport.padBottom as number); - let width = this.previousViewport.width + (this.previousViewport.padLeft as number) + (this.previousViewport.padRight as number); - let height = this.previousViewport.height + (this.previousViewport.padBottom as number) + (this.previousViewport.padTop as number); + const x = this.previousViewport.x - (this.previousViewport.padLeft as number); + const y = this.previousViewport.y - (this.previousViewport.padBottom as number); + const width = this.previousViewport.width + (this.previousViewport.padLeft as number) + (this.previousViewport.padRight as number); + const height = this.previousViewport.height + (this.previousViewport.padBottom as number) + (this.previousViewport.padTop as number); viewport.x = x + (viewport.x - x) * transitionAlpha; viewport.y = y + (viewport.y - y) * transitionAlpha; viewport.width = width + (viewport.width - width) * transitionAlpha; @@ -898,7 +890,7 @@ export class SpinePlayer implements Disposable { } } - let renderer = this.sceneRenderer!; + const renderer = this.sceneRenderer!; renderer.camera.zoom = this.canvas!.height / this.canvas!.width > viewport.height / viewport.width ? viewport.width / this.canvas!.width : viewport.height / this.canvas!.height; renderer.camera.position.x = viewport.x + viewport.width / 2; @@ -908,7 +900,7 @@ export class SpinePlayer implements Disposable { renderer.resize(this.currentViewport.clip ? ResizeMode.FitClip : ResizeMode.Fit, viewport.width, viewport.height); // Clear the screen. - let gl = this.context!.gl; + const gl = this.context!.gl; gl.clearColor(bg.r, bg.g, bg.b, bg.a); gl.clear(gl.COLOR_BUFFER_BIT); @@ -917,9 +909,9 @@ export class SpinePlayer implements Disposable { renderer.begin(); // Draw the background image. - let bgImage = config.backgroundImage; + const bgImage = config.backgroundImage; if (bgImage) { - let texture = this.assetManager!.require(bgImage.url) as GLTexture; + const 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 @@ -940,15 +932,15 @@ export class SpinePlayer implements Disposable { } // Draw the control bones. - let controlBones = config.controlBones!; + const controlBones = config.controlBones!; if (controlBones.length) { - let selectedBones = this.selectedBones; + const selectedBones = this.selectedBones; gl.lineWidth(2); for (let i = 0; i < controlBones.length; i++) { - let bone = skeleton.findBone(controlBones[i]); + const bone = skeleton.findBone(controlBones[i]); if (!bone) continue; - let colorInner = selectedBones[i] ? BONE_INNER_OVER : BONE_INNER; - let colorOuter = selectedBones[i] ? BONE_OUTER_OVER : BONE_OUTER; + const colorInner = selectedBones[i] ? BONE_INNER_OVER : BONE_INNER; + const colorOuter = selectedBones[i] ? BONE_OUTER_OVER : BONE_OUTER; const applied = bone.applied; renderer.circle(true, skeleton.x + applied.worldX, skeleton.y + applied.worldY, 20, colorInner); renderer.circle(false, skeleton.x + applied.worldX, skeleton.y + applied.worldY, 20, colorOuter); @@ -992,10 +984,10 @@ export class SpinePlayer implements Disposable { } private showSpeedDialog (speedButton: HTMLElement) { - let id = "speed"; + const id = "speed"; if (this.hidePopup(id)) return; - let popup = new Popup(id, speedButton, this, this.playerControls!, /*html*/` + const popup = new Popup(id, speedButton, this, this.playerControls!, /*html*/`
Speed

@@ -1004,7 +996,7 @@ export class SpinePlayer implements Disposable {
0.1x
1x
2x
`); - let slider = new Slider(2, 0.1, true); + const slider = new Slider(2, 0.1, true); findWithClass(popup.dom, "spine-player-speed-slider").appendChild(slider.create()); slider.setValue(this.speed / 2); slider.change = (percentage) => this.speed = percentage * 2; @@ -1012,21 +1004,21 @@ export class SpinePlayer implements Disposable { } private showAnimationsDialog (animationsButton: HTMLElement) { - let id = "animations"; + const id = "animations"; if (this.hidePopup(id)) return; if (!this.skeleton || !this.skeleton.data.animations.length) return; - let popup = new Popup(id, animationsButton, this, this.playerControls!, + const popup = new Popup(id, animationsButton, this, this.playerControls!, /*html*/`
Animations

    `); - let rows = findWithClass(popup.dom, "spine-player-list"); + const rows = findWithClass(popup.dom, "spine-player-list"); this.skeleton.data.animations.forEach((animation) => { // Skip animations not whitelisted if a whitelist was given. if (this.config.animations && this.config.animations.indexOf(animation.name) < 0) return; - let row = createElement( + const row = createElement( /*html*/`
  • `); - if (animation.name == this.config.animation) row.classList.add("selected"); + if (animation.name === this.config.animation) row.classList.add("selected"); findWithClass(row, "selectable-text").innerText = animation.name; rows.appendChild(row); row.onclick = () => { @@ -1042,20 +1034,20 @@ export class SpinePlayer implements Disposable { } private showSkinsDialog (skinButton: HTMLElement) { - let id = "skins"; + const id = "skins"; if (this.hidePopup(id)) return; if (!this.skeleton || !this.skeleton.data.animations.length) return; - let popup = new Popup(id, skinButton, this, this.playerControls!, + const popup = new Popup(id, skinButton, this, this.playerControls!, /*html*/`
    Skins

      `); - let rows = findWithClass(popup.dom, "spine-player-list"); + const rows = findWithClass(popup.dom, "spine-player-list"); this.skeleton.data.skins.forEach((skin) => { // Skip skins not whitelisted if a whitelist was given. if (this.config.skins && this.config.skins.indexOf(skin.name) < 0) return; - let row = createElement(/*html*/`
    • `); - if (skin.name == this.config.skin) row.classList.add("selected"); + const row = createElement(/*html*/`
    • `); + if (skin.name === this.config.skin) row.classList.add("selected"); findWithClass(row, "selectable-text").innerText = skin.name; rows.appendChild(row); row.onclick = () => { @@ -1070,18 +1062,18 @@ export class SpinePlayer implements Disposable { } private showSettingsDialog (settingsButton: HTMLElement) { - let id = "settings"; + const id = "settings"; if (this.hidePopup(id)) return; if (!this.skeleton || !this.skeleton.data.animations.length) return; - let popup = new Popup(id, settingsButton, this, this.playerControls!, /*html*/`
      Debug

        `); + const popup = new Popup(id, settingsButton, this, this.playerControls!, /*html*/`
        Debug

          `); - let rows = findWithClass(popup.dom, "spine-player-list"); - let makeItem = (label: string, name: string) => { - let row = createElement(/*html*/`
        • `); - let s = new Switch(label); + const rows = findWithClass(popup.dom, "spine-player-list"); + const makeItem = (label: string, name: string) => { + const row = createElement(/*html*/`
        • `); + const s = new Switch(label); row.appendChild(s.create()); - let debug = this.config.debug as any; + const debug = this.config.debug as any; s.setEnabled(debug[name]); s.change = (value) => debug[name] = value; rows.appendChild(row); @@ -1107,7 +1099,6 @@ export class SpinePlayer implements Disposable { + message.replace("\n", "

          ") + `
      `)); if (this.config.error) this.config.error(this, message); throw (error ? error : new Error(message)); - console.log(error); } } } @@ -1121,7 +1112,7 @@ class Popup { this.dom = createElement(/*html*/`
      `); this.dom.innerHTML = htmlContent; parent.appendChild(this.dom); - this.className = "spine-player-button-icon-" + id + "-selected"; + this.className = `spine-player-button-icon-${id}-selected`; } dispose () { @@ -1131,7 +1122,7 @@ class Popup { hide (id: string): boolean { this.dom.remove(); this.button.classList.remove(this.className); - if (this.id == id) { + if (this.id === id) { this.player.popup = null; return true; } @@ -1145,19 +1136,19 @@ class Popup { // Make sure the popup isn't bigger than the player. let dismissed = false; - let resize = () => { + const resize = () => { if (!dismissed) requestAnimationFrame(resize); - let playerDom = this.player.dom; - let bottomOffset = Math.abs(playerDom.getBoundingClientRect().bottom - playerDom.getBoundingClientRect().bottom); - let rightOffset = Math.abs(playerDom.getBoundingClientRect().right - playerDom.getBoundingClientRect().right); - this.dom.style.maxHeight = (playerDom.clientHeight - bottomOffset - rightOffset) + "px"; + const playerDom = this.player.dom; + const bottomOffset = Math.abs(playerDom.getBoundingClientRect().bottom - playerDom.getBoundingClientRect().bottom); + const rightOffset = Math.abs(playerDom.getBoundingClientRect().right - playerDom.getBoundingClientRect().right); + this.dom.style.maxHeight = `${playerDom.clientHeight - bottomOffset - rightOffset}px`; } requestAnimationFrame(resize); // Dismiss when clicking somewhere outside the popup. let justClicked = true; - let windowClickListener = (event: any) => { - if (justClicked || this.player.popup != this) { + const windowClickListener = (event: any) => { + if (justClicked || this.player.popup !== this) { justClicked = false; return; } @@ -1250,8 +1241,8 @@ class Slider { setValue (percentage: number): number { percentage = Math.max(0, Math.min(1, percentage)); if (this.snaps) { - let snap = 1 / this.snaps; - let modulo = percentage % snap; + const snap = 1 / this.snaps; + const modulo = percentage % snap; // floor if (modulo < snap * this.snapPercentage) percentage = percentage - modulo; @@ -1259,7 +1250,7 @@ class Slider { percentage = percentage - modulo + snap; percentage = Math.max(0, Math.min(1, percentage)); } - this.value!.style.width = "" + (percentage * 100) + "%"; + this.value!.style.width = `${percentage * 100}%`; // this.knob.style.left = "" + (-8 + percentage * this.slider.clientWidth) + "px"; return percentage; } @@ -1270,7 +1261,7 @@ function findWithClass (element: HTMLElement, className: string): HTMLElement { } function createElement (html: string): HTMLElement { - let div = document.createElement("div"); + const div = document.createElement("div"); div.innerHTML = html; return div.children[0] as HTMLElement; } @@ -1280,7 +1271,7 @@ function removeClass (elements: HTMLCollection, clazz: string) { elements[i].classList.remove(clazz); } -function toString (object: any) { +function print (object: any) { return JSON.stringify(object) .replace(/&/g, "&") .replace(/
      `; parent.innerHTML = dom; - let codeElement = parent.children[0].children[0]; + const codeElement = parent.children[0].children[0]; this.player = parent.children[0].children[1] as HTMLIFrameElement; requestAnimationFrame(() => { diff --git a/spine-ts/spine-player/src/index.ts b/spine-ts/spine-player/src/index.ts index 4fc9c0a42..ee7fde7e3 100644 --- a/spine-ts/spine-player/src/index.ts +++ b/spine-ts/spine-player/src/index.ts @@ -1,4 +1,4 @@ -export * from './Player.js'; -export * from './PlayerEditor.js'; export * from "@esotericsoftware/spine-core"; -export * from "@esotericsoftware/spine-webgl"; \ No newline at end of file +export * from "@esotericsoftware/spine-webgl"; +export * from './Player.js'; +export * from './PlayerEditor.js'; \ No newline at end of file diff --git a/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts b/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts index 297b43ace..ab52829e9 100644 --- a/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts +++ b/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts @@ -27,9 +27,9 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { AssetCache, AssetManager, Color, Disposable, Input, LoadingScreen, ManagedWebGLRenderingContext, Physics, SceneRenderer, TimeKeeper, Vector2, Vector3 } from "@esotericsoftware/spine-webgl" -import { SpineWebComponentSkeleton } from "./SpineWebComponentSkeleton.js" -import { AttributeTypes, castValue, Point, Rectangle } from "./wcUtils.js" +import { AssetCache, AssetManager, type Bone, Color, type Disposable, Input, LoadingScreen, ManagedWebGLRenderingContext, Physics, SceneRenderer, type Skeleton, TimeKeeper, Vector2, Vector3 } from "@esotericsoftware/spine-webgl" +import type { SpineWebComponentSkeleton } from "./SpineWebComponentSkeleton.js" +import { type AttributeTypes, castValue, type Point, type Rectangle } from "./wcUtils.js" interface OverlayAttributes { overlayId?: string @@ -41,6 +41,8 @@ interface OverlayAttributes { } export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes, Disposable { + declare parentElement: HTMLElement; + private static OVERLAY_ID = "spine-overlay-default-identifier"; private static OVERLAY_LIST = new Map(); @@ -66,7 +68,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr /** * A list holding the widgets added to this overlay. */ - public widgets = new Array(); + public widgets = [] as SpineWebComponentSkeleton[]; /** * The {@link SceneRenderer} used by this overlay. @@ -256,7 +258,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const { target, intersectionRatio } = elem; let { isIntersecting } = elem; for (const widget of this.widgets) { - if (widget.getHostElement() != target) continue; + if (widget.getHostElement() !== target) continue; // old browsers do not have isIntersecting if (isIntersecting === undefined) { @@ -277,13 +279,13 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr if (this.hasCssTweakOff()) { this.hasParentTransform = false; } else { - this.parentElement!.style.transform = `translateZ(0)`; + this.parentElement.style.transform = `translateZ(0)`; } } else { window.addEventListener("resize", this.windowResizeCallback); } this.resizeObserver = new ResizeObserver(() => this.resizedCallback()); - this.resizeObserver.observe(this.parentElement!); + this.resizeObserver.observe(this.parentElement); for (const widget of this.widgets) { this.intersectionObserver?.observe(widget.getHostElement()); @@ -308,7 +310,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr this.input?.dispose(); } - static attributesDescription: Record = { + static attributesDescription: Record = { "overlay-id": { propertyName: "overlayId", type: "string" }, "no-auto-parent-transform": { propertyName: "noAutoParentTransform", type: "boolean" }, "overflow-top": { propertyName: "overflowTop", type: "number" }, @@ -324,7 +326,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr attributeChangedCallback (name: string, oldValue: string | null, newValue: string | null): void { const { type, propertyName, defaultValue } = SpineWebComponentOverlay.attributesDescription[name]; const val = castValue(type, newValue, defaultValue); - (this as any)[propertyName] = val; + (this[propertyName] as OverlayAttributes[typeof propertyName]) = val as OverlayAttributes[typeof propertyName]; return; } @@ -360,12 +362,12 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr this.scrolledCallback(); if (!this.loaded) { this.loaded = true; - this.parentElement!.appendChild(this); + this.parentElement.appendChild(this); } } private hasCssTweakOff () { - return this.noAutoParentTransform && getComputedStyle(this.parentElement!).transform === "none"; + return this.noAutoParentTransform && getComputedStyle(this.parentElement).transform === "none"; } /** @@ -393,7 +395,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const comparison = this.compareDocumentPosition(widget); // DOCUMENT_POSITION_DISCONNECTED is needed when a widget is inside the overlay (due to followBone) if ((comparison & Node.DOCUMENT_POSITION_FOLLOWING) && !(comparison & Node.DOCUMENT_POSITION_DISCONNECTED)) { - this.parentElement!.appendChild(this); + this.parentElement.appendChild(this); } } @@ -448,7 +450,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr this.div.appendChild(this.fps); this.fpsAppended = true; } - this.fps.innerText = this.time.framesPerSecond.toFixed(2) + " fps"; + this.fps.innerText = `${this.time.framesPerSecond.toFixed(2)} fps`; } else { if (this.fpsAppended) { this.div.removeChild(this.fps); @@ -482,15 +484,15 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const renderWidgets = () => { clear(0, 0, 0, 0); - let renderer = this.renderer; + const renderer = this.renderer; renderer.begin(); let ref: DOMRect; let offsetLeftForOevrlay = 0; let offsetTopForOverlay = 0; if (!this.appendedToBody) { - ref = this.parentElement!.getBoundingClientRect(); - const computedStyle = getComputedStyle(this.parentElement!); + ref = this.parentElement.getBoundingClientRect(); + const computedStyle = getComputedStyle(this.parentElement); offsetLeftForOevrlay = ref.left + parseFloat(computedStyle.borderLeftWidth); offsetTopForOverlay = ref.top + parseFloat(computedStyle.borderTopWidth); } @@ -532,7 +534,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr if (loading) { if (spinner) { if (!widget.loadingScreen) widget.loadingScreen = new LoadingScreen(renderer); - widget.loadingScreen!.drawInCoordinates(divOriginX, divOriginY); + widget.loadingScreen?.drawInCoordinates(divOriginX, divOriginY); } if (clip) endScissor(); continue; @@ -540,7 +542,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr if (skeleton) { if (fit !== "origin") { - let { x: ax, y: ay, width: aw, height: ah } = bounds; + const { x: ax, y: ay, width: aw, height: ah } = bounds; if (aw <= 0 || ah <= 0) continue; // scale ratio @@ -622,7 +624,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // drawing debug stuff if (debug) { // if (true) { - let { x: ax, y: ay, width: aw, height: ah } = bounds; + const { x: ax, y: ay, width: aw, height: ah } = bounds; // show bounds and its center if (drag) { @@ -645,7 +647,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr renderer.circle(true, bbCenterX, bbCenterY, 10, blue); // show skeleton root - const root = skeleton.getRootBone()!; + const root = skeleton.getRootBone() as Bone; renderer.circle(true, root.applied.x + worldOffsetX, root.applied.y + worldOffsetY, 10, red); // show shifted origin @@ -720,7 +722,6 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const red = new Color(1, 0, 0, 1); const green = new Color(0, 1, 0, 1); const blue = new Color(0, 0, 1, 1); - const transparentWhite = new Color(1, 1, 1, .3); const transparentRed = new Color(1, 0, 0, .3); } @@ -735,12 +736,12 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr this.pointerCanvasY = input.y - window.scrollY; if (!this.appendedToBody) { - const ref = this.parentElement!.getBoundingClientRect(); + const ref = this.parentElement.getBoundingClientRect(); this.pointerCanvasX -= ref.left; this.pointerCanvasY -= ref.top; } - let tempVector = this.tempVector; + const tempVector = this.tempVector; tempVector.set(this.pointerCanvasX, this.pointerCanvasY, 0); this.renderer.camera.screenToWorld(tempVector, this.canvas.clientWidth, this.canvas.clientHeight); @@ -763,8 +764,8 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const inputManager = new Input(document.body, false) const inputPointTemp: Point = new Vector2(); - const getInput = (ev?: MouseEvent | TouchEvent): Point => { - const originalEvent = ev instanceof MouseEvent ? ev : ev!.changedTouches[0]; + const getInput = (ev: MouseEvent | TouchEvent): Point => { + const originalEvent = ev instanceof MouseEvent ? ev : ev.changedTouches[0]; inputPointTemp.x = originalEvent.pageX + this.overflowLeftSize; inputPointTemp.y = originalEvent.pageY + this.overflowTopSize; return inputPointTemp; @@ -774,7 +775,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let lastY = 0; inputManager.addListener({ // moved is used to pass pointer position wrt to canvas and widget position and currently is EXPERIMENTAL - moved: (x, y, ev) => { + moved: (x, y, ev: MouseEvent | TouchEvent) => { const input = getInput(ev); this.updatePointer(input); @@ -784,7 +785,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr widget.pointerEventUpdate("move", ev); } }, - down: (x, y, ev) => { + down: (x, y, ev: MouseEvent | TouchEvent) => { const input = getInput(ev); this.updatePointer(input); @@ -805,11 +806,11 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr lastX = input.x; lastY = input.y; }, - dragged: (x, y, ev) => { + dragged: (x, y, ev: MouseEvent | TouchEvent) => { const input = getInput(ev); - let dragX = input.x - lastX; - let dragY = input.y - lastY; + const dragX = input.x - lastX; + const dragY = input.y - lastY; this.updatePointer(input); @@ -820,7 +821,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr if (!widget.dragging) continue; - const skeleton = widget.skeleton!; + const skeleton = widget.skeleton as Skeleton; widget.dragX += this.screenToWorldLength(dragX); widget.dragY -= this.screenToWorldLength(dragY); skeleton.physicsTranslate(dragX, -dragY); @@ -861,8 +862,8 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const totalWidth = width * (1 + (this.overflowLeft + this.overflowRight)); const totalHeight = height * (1 + (this.overflowTop + this.overflowBottom)); - this.canvas.style.width = totalWidth + "px"; - this.canvas.style.height = totalHeight + "px"; + this.canvas.style.width = `${totalWidth}px`; + this.canvas.style.height = `${totalHeight}px`; this.resize(totalWidth, totalHeight); } @@ -872,28 +873,28 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // this.div?.remove(); is it better width/height to zero? // this.div!.style.width = 0 + "px"; // this.div!.style.height = 0 + "px"; - this.div!.style.display = "none"; + this.div.style.display = "none"; if (this.appendedToBody) { const { width, height } = this.getPageSize(); - this.div!.style.width = width + "px"; - this.div!.style.height = height + "px"; + this.div.style.width = `${width}px`; + this.div.style.height = `${height}px`; } else { if (this.hasCssTweakOff()) { // this case lags if scrolls or position fixed. Users should never use tweak off - this.div!.style.width = this.parentElement!.clientWidth + "px"; - this.div!.style.height = this.parentElement!.clientHeight + "px"; + this.div.style.width = `${this.parentElement.clientWidth}px`; + this.div.style.height = `${this.parentElement.clientHeight}px`; this.canvas.style.transform = `translate(${-this.overflowLeftSize}px,${-this.overflowTopSize}px)`; } else { - this.div!.style.width = this.parentElement!.scrollWidth + "px"; - this.div!.style.height = this.parentElement!.scrollHeight + "px"; + this.div.style.width = `${this.parentElement.scrollWidth}px`; + this.div.style.height = `${this.parentElement.scrollHeight}px`; } } - this.div!.style.display = ""; + this.div.style.display = ""; // this.root.appendChild(this.div!); } private resize (width: number, height: number) { - let canvas = this.canvas; + const canvas = this.canvas; canvas.width = Math.round(this.screenToWorldLength(width)); canvas.height = Math.round(this.screenToWorldLength(height)); this.renderer.context.gl.viewport(0, 0, canvas.width, canvas.height); @@ -921,13 +922,13 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr private getViewportSize (): { width: number, height: number } { if (!this.appendedToBody) { return { - width: this.parentElement!.clientWidth, - height: this.parentElement!.clientHeight, + width: this.parentElement.clientWidth, + height: this.parentElement.clientHeight, } } - let width = window.innerWidth; - let height = window.innerHeight; + const width = window.innerWidth; + const height = window.innerHeight; const dpr = this.getDevicePixelRatio(); if (dpr !== this.lastDPR) { @@ -993,10 +994,10 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // Ideally this should be the only appendedToBody case (no-auto-parent-transform not enabled or at least an ancestor has transform) // I'd like to get rid of the else case if (this.hasParentTransform) { - scrollPositionX += this.parentElement!.scrollLeft; - scrollPositionY += this.parentElement!.scrollTop; + scrollPositionX += this.parentElement.scrollLeft; + scrollPositionY += this.parentElement.scrollTop; } else { - const { left, top } = this.parentElement!.getBoundingClientRect(); + const { left, top } = this.parentElement.getBoundingClientRect(); scrollPositionX += left + window.scrollX; scrollPositionY += top + window.scrollY; @@ -1027,10 +1028,10 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let parent: HTMLElement | null = element; let zIndex: undefined | number; do { - let currentZIndex = parseInt(getComputedStyle(parent).zIndex); + const currentZIndex = parseInt(getComputedStyle(parent).zIndex); // searching the shallowest z-index - if (!isNaN(currentZIndex)) zIndex = currentZIndex; + if (!Number.isNaN(currentZIndex)) zIndex = currentZIndex; parent = parent.parentElement; } while (parent && parent !== document.body) diff --git a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts index 69cce4411..f3f802eab 100644 --- a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts +++ b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts @@ -28,31 +28,32 @@ *****************************************************************************/ import { - Animation, + type Animation, AnimationState, AnimationStateData, AtlasAttachmentLoader, - Bone, - Disposable, - LoadingScreen, + type Bone, + type Disposable, + type LoadingScreen, MeshAttachment, MixBlend, MixDirection, - NumberArrayLike, + type NumberArrayLike, Physics, RegionAttachment, Skeleton, SkeletonBinary, - SkeletonData, + type SkeletonData, SkeletonJson, Skin, - Slot, - TextureAtlas, + type Slot, + type TextureAtlas, + type TrackEntry, Utils, Vector2, } from "@esotericsoftware/spine-webgl"; import { SpineWebComponentOverlay } from "./SpineWebComponentOverlay.js"; -import { AttributeTypes, castValue, isBase64, Rectangle } from "./wcUtils.js"; +import { type AttributeTypes, castValue, isBase64, type Rectangle } from "./wcUtils.js"; type UpdateSpineWidgetFunction = (delta: number, skeleton: Skeleton, state: AnimationState) => void; @@ -456,10 +457,10 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable } private getSlotFromRef (slotRef: number | string | Slot): Slot { - let slot: Slot | null; + let slot: Slot | null | undefined; - if (typeof slotRef === 'number') slot = this.skeleton!.slots[slotRef]; - else if (typeof slotRef === 'string') slot = this.skeleton!.findSlot(slotRef); + if (typeof slotRef === 'number') slot = this.skeleton?.slots[slotRef]; + else if (typeof slotRef === 'string') slot = this.skeleton?.findSlot(slotRef); else slot = slotRef; if (!slot) throw new Error(`No slot found with the given slot reference: ${slotRef}`); @@ -686,7 +687,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable // - remove appendTo that is just to avoid the user to use the overlayAssignedPromise when the widget is created using js private overlayAssignedPromise: Promise; - static attributesDescription: Record = { + static attributesDescription: Record = { atlas: { propertyName: "atlasPath", type: "string" }, skeleton: { propertyName: "skeletonPath", type: "string" }, "raw-data": { propertyName: "rawData", type: "object" }, @@ -776,7 +777,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable window.removeEventListener("DOMContentLoaded", this.DOMContentLoadedCallback); const index = this.overlay?.widgets.indexOf(this); if (index > 0) { - this.overlay!.widgets.splice(index, 1); + this.overlay?.widgets.splice(index, 1); } } @@ -797,7 +798,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable attributeChangedCallback (name: string, oldValue: string | null, newValue: string | null): void { const { type, propertyName, defaultValue } = SpineWebComponentSkeleton.attributesDescription[name]; const val = castValue(type, newValue, defaultValue); - (this as any)[propertyName] = val; + (this[propertyName] as WidgetAttributes[typeof propertyName]) = val as WidgetAttributes[typeof propertyName]; return; } @@ -830,12 +831,12 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable * @param atlas the `TextureAtlas` from which to get the `TextureAtlasPage`s * @returns The list of loaded assets */ - public async loadTexturesInPagesAttribute (): Promise> { - const atlas = this.overlay.assetManager.require(this.atlasPath!) as TextureAtlas; + public async loadTexturesInPagesAttribute (): Promise> { + const atlas = this.overlay.assetManager.require(this.atlasPath as string) as TextureAtlas; const pagesIndexToLoad = this.pages ?? atlas.pages.map((_, i) => i); // if no pages provided, loads all const atlasPath = this.atlasPath?.includes("/") ? this.atlasPath.substring(0, this.atlasPath.lastIndexOf("/") + 1) : ""; - const promisePageList: Array> = []; - const texturePaths = []; + const promisePageList: Array> = []; + const texturePaths = [] as string[]; for (const index of pagesIndexToLoad) { const page = atlas.pages[index]; @@ -866,7 +867,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable */ public getHostElement (): HTMLElement { return (this.width <= 0 || this.width <= 0) && !this.getAttribute("style") && !this.getAttribute("class") - ? this.parentElement! + ? this.parentElement as HTMLElement : this; } @@ -934,7 +935,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable const isBinary = skeletonPath.endsWith(".skel"); if (rawData) { - for (let [key, value] of Object.entries(rawData)) { + for (const [key, value] of Object.entries(rawData)) { this.overlay.assetManager.setRawDataURI(key, isBase64(value) ? `data:application/octet-stream;base64,${value}` : value); } } @@ -1032,7 +1033,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable const cycleFn = () => { const trackIndex = Number(trackIndexString); for (const [index, { animationName, delay, loop, mixDuration }] of animations.entries()) { - let track; + let track: TrackEntry; if (index === 0) { if (animationName === "#EMPTY#") { track = state.setEmptyAnimation(trackIndex, mixDuration); @@ -1076,7 +1077,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable } private render (): void { - let noSize = (!this.getAttribute("style") && !this.getAttribute("class")); + const noSize = (!this.getAttribute("style") && !this.getAttribute("class")); this.root.innerHTML = `