diff --git a/release/MAC版本/LICENSES/Spine-3.4-License.txt b/release/MAC版本/LICENSES/Spine-3.4-License.txt new file mode 100644 index 0000000..9e0f60d --- /dev/null +++ b/release/MAC版本/LICENSES/Spine-3.4-License.txt @@ -0,0 +1,33 @@ +Source revision: ef5013143178918ddfc7cabfbddeae7aec7cf84e (official 3.4.02 tag) +Runtime: https://github.com/EsotericSoftware/spine-runtimes/blob/3.4.02/spine-ts/build/spine-canvas.js +Binary parser source: https://github.com/EsotericSoftware/spine-runtimes/blob/3.4.02/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java + +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ diff --git a/release/MAC版本/LICENSES/Spine-3.5-License.txt b/release/MAC版本/LICENSES/Spine-3.5-License.txt new file mode 100644 index 0000000..6bec3a2 --- /dev/null +++ b/release/MAC版本/LICENSES/Spine-3.5-License.txt @@ -0,0 +1,33 @@ +Source revision: 2cd9467d2736b7f3a0b81382f117c73823bfb44b (official 3.5.51 tag) +Runtime: https://github.com/EsotericSoftware/spine-runtimes/blob/3.5.51/spine-ts/build/spine-canvas.js +Binary parser source: https://github.com/EsotericSoftware/spine-runtimes/blob/3.5.51/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java + +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ diff --git a/release/MAC版本/LICENSES/Spine-Legacy-Binary-License.txt b/release/MAC版本/LICENSES/Spine-Legacy-Binary-License.txt new file mode 100644 index 0000000..1974c99 --- /dev/null +++ b/release/MAC版本/LICENSES/Spine-Legacy-Binary-License.txt @@ -0,0 +1,62 @@ +Source: https://github.com/EsotericSoftware/spine-runtimes/blob/3.6/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + + +Source: https://github.com/EsotericSoftware/spine-runtimes/blob/3.7/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated May 1, 2019. Replaces all prior versions. + * + * Copyright (c) 2013-2019, 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. + * + * THIS SOFTWARE IS 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 THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + diff --git a/release/MAC版本/LICENSES/Spine-Runtimes-License.txt b/release/MAC版本/LICENSES/Spine-Runtimes-License.txt new file mode 100644 index 0000000..517ff9f --- /dev/null +++ b/release/MAC版本/LICENSES/Spine-Runtimes-License.txt @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated April 5, 2025. Replaces all prior versions. + +Copyright (c) 2013-2025, 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: +https://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. diff --git a/release/MAC版本/LICENSES/napi-rs-canvas-LICENSE.txt b/release/MAC版本/LICENSES/napi-rs-canvas-LICENSE.txt new file mode 100644 index 0000000..e002407 --- /dev/null +++ b/release/MAC版本/LICENSES/napi-rs-canvas-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 lynweklm@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/release/MAC版本/README.md b/release/MAC版本/README.md new file mode 100644 index 0000000..0f24ee6 --- /dev/null +++ b/release/MAC版本/README.md @@ -0,0 +1,34 @@ +# SpineViewer 1.1.0 + +Eagle 的离线 Spine 骨骼动画预览插件,支持 Spine 3.4、3.5、3.6、3.7、3.8、4.0、4.1、4.2、4.3。 + +## 功能与使用 + +1. 将同一套骨骼文件(`.skel` / `.skel.bytes` / Spine `.json`)、图集(`.atlas` / `.atlas.txt`)和配套贴图一起导入 Eagle,建议放在同一个 Eagle 文件夹内,并保留文件名配对关系。 +2. 打开骨骼或图集文件即可预览。普通图片仍使用 Eagle 原生预览。 +3. 支持动画和皮肤切换、播放/暂停(空格)、循环、速度、时间轴拖动、缩放适配、背景与预乘 Alpha(PMA)切换。 +4. 自动生成带 Spine 标记和版本号的缩略图,也可在预览器中将当前帧设为缩略图。资源未配齐时先显示占位图,补齐后会尝试自动刷新。 + +所有运行时均随包提供,无需联网。缺少或不匹配的原生 Canvas 依赖会使自动缩略图降级为占位图。 + +## 打包与平台替换 + +本目录就是插件根目录,在 Eagle 中加载此目录,再使用插件的“打包插件”功能生成 `.eagleplugin`;接收者安装生成的文件即可。 + +当前附带 **macOS Apple 芯片** 的 `@napi-rs/canvas` **0.1.66**。清单保留源码的 `all/all` 设置,正式出包前请根据下表手动设置 `manifest.json` 的 `platform` 和 `arch`。 + +保留 `node_modules/@napi-rs/canvas/` 公共目录,将同级的 `canvas-darwin-arm64/` 替换为目标平台的完整包目录(不要只改目录名),所有原生包版本必须为 **0.1.66**: + +| 目标平台 | `node_modules/@napi-rs/` 下的原生包目录 | platform | arch | +| --- | --- | --- | --- | +| macOS Apple 芯片 | `canvas-darwin-arm64/`(已附带) | `mac` | `arm` | +| macOS Intel | `canvas-darwin-x64/` | `mac` | `x64` | +| Windows x64 | `canvas-win32-x64-msvc/` | `win` | `x64` | + +对应目录中应包含 `package.json` 和原生文件 `skia.darwin-arm64.node`、`skia.darwin-x64.node` 或 `skia.win32-x64-msvc.node`。可在目标系统的临时目录复制本包的 `package.json`、`package-lock.json`,运行 `npm ci --omit=dev`,然后将生成的整个 `node_modules/` 替换到本目录。按实际运行进程架构选择依赖;Apple 芯片上以 Rosetta 运行的 x64 进程需要 x64 依赖。 + +如制作包含多个平台的合并包,可将所需原生包目录并排保留,公共 `canvas/` 只保留一份;覆盖并验证所有目标平台后再使用 `all/all`。平台字段见 [Eagle 官方说明](https://developer.eagle.cool/plugin-api/tutorial/manifest)。 + +打包前在目标 Eagle 中检查一次动画预览和自动缩略图;本目录未附带 Windows / Intel Mac 二进制,也未在这些系统上验证。 + +第三方许可证见 `LICENSES/`,分发时请保留。 diff --git a/release/MAC版本/assets/README.md b/release/MAC版本/assets/README.md new file mode 100644 index 0000000..9dd147e --- /dev/null +++ b/release/MAC版本/assets/README.md @@ -0,0 +1,5 @@ +# Spine badge + +`spine-badge.png` 下载自 Esoteric Software 官方 [Spine Brand assets](https://esotericsoftware.com/branding) 页面。 + +插件只在缩略图右下角等比缩放显示该 badge,用于标明条目是 Spine 数据文件;图形本身未做拉伸、变色或其他修改。 diff --git a/release/MAC版本/assets/spine-badge.png b/release/MAC版本/assets/spine-badge.png new file mode 100644 index 0000000..422f11a Binary files /dev/null and b/release/MAC版本/assets/spine-badge.png differ diff --git a/release/MAC版本/js/eagle-compound.js b/release/MAC版本/js/eagle-compound.js new file mode 100644 index 0000000..d83a939 --- /dev/null +++ b/release/MAC版本/js/eagle-compound.js @@ -0,0 +1,17 @@ +'use strict'; +const path = require('path'); + +// Preserve name + '.' + ext exactly; only split the compound suffix correctly. +// Return through Eagle's thumbnail callback so Eagle persists its own metadata. +function normalizeItem(src, item) { + const filename = path.basename(src); + const match = filename.match(/^(.*)\.(atlas\.txt|skel\.bytes)$/i); + if (!match || !item || !item.ext) return false; + if (item.name + '.' + item.ext !== filename) return false; + if (item.name === match[1] && item.ext === match[2]) return false; + item.name = match[1]; item.ext = match[2]; + delete item.text; + return true; +} + +module.exports = { normalizeItem }; diff --git a/release/MAC版本/js/spine-background.js b/release/MAC版本/js/spine-background.js new file mode 100644 index 0000000..1c705d5 --- /dev/null +++ b/release/MAC版本/js/spine-background.js @@ -0,0 +1,25 @@ +'use strict'; +const patterns = new WeakMap(); + +// Called with the same world-to-canvas transform used to draw the skeleton. +function drawCheckerboard(ctx, width, height) { + let pattern = patterns.get(ctx); + if (!pattern) { + const tile = ctx.canvas.ownerDocument.createElement('canvas'); + tile.width = tile.height = 100; + const paint = tile.getContext('2d'); + paint.fillStyle = '#505052'; paint.fillRect(0, 0, 100, 100); + paint.fillStyle = '#5a5a5c'; paint.fillRect(0, 0, 50, 50); paint.fillRect(50, 50, 50, 50); + pattern = ctx.createPattern(tile, 'repeat'); patterns.set(ctx, pattern); + } + const m = ctx.getTransform().inverse(); + const corners = [[0,0], [width,0], [width,height], [0,height]].map(([x,y]) => [m.a*x+m.c*y+m.e, m.b*x+m.d*y+m.f]); + const xs = corners.map(p => p[0]), ys = corners.map(p => p[1]); + const x = Math.min(...xs), y = Math.min(...ys); + if (!Number.isFinite(x + y)) return; + ctx.save(); + try { ctx.imageSmoothingEnabled = false; ctx.fillStyle = pattern; ctx.fillRect(x, y, Math.max(...xs)-x, Math.max(...ys)-y); } + finally { ctx.restore(); } +} + +module.exports = { drawCheckerboard }; diff --git a/release/MAC版本/js/spine-badge.js b/release/MAC版本/js/spine-badge.js new file mode 100644 index 0000000..8466924 --- /dev/null +++ b/release/MAC版本/js/spine-badge.js @@ -0,0 +1,31 @@ +const fs = require('fs'); +const path = require('path'); + +const badgePath = path.join(__dirname, '..', 'assets', 'spine-badge.png'); +let cachedDataUrl = null; + +function dataUrl() { + if (!cachedDataUrl) { + cachedDataUrl = 'data:image/png;base64,' + fs.readFileSync(badgePath).toString('base64'); + } + return cachedDataUrl; +} + +function drawVersion(ctx, width, height, version) { + version = String(version || ''); + if (version.length > 40 || !/^\d+\.\d+(?:\.\d+)?(?:[-+][a-z0-9][a-z0-9.-]*)?$/i.test(version)) return; + const fontSize = Math.max(12, Math.round(Math.min(width, height) * 0.055)); + const margin = Math.max(10, Math.round(Math.min(width, height) * 0.03)); + ctx.save(); + try { + ctx.font = '600 ' + fontSize + 'px sans-serif'; + ctx.textAlign = 'left'; ctx.textBaseline = 'middle'; + const boxHeight = fontSize + 12; + const y = height - margin - boxHeight; + ctx.fillStyle = 'rgba(0,0,0,0.65)'; + ctx.fillRect(margin, y, ctx.measureText(version).width + 16, boxHeight); + ctx.fillStyle = '#ffffff'; ctx.fillText(version, margin + 8, y + boxHeight / 2); + } finally { ctx.restore(); } +} + +module.exports = { path: badgePath, dataUrl, drawVersion }; diff --git a/release/MAC版本/js/spine-canvas-clipping.js b/release/MAC版本/js/spine-canvas-clipping.js new file mode 100644 index 0000000..e055548 --- /dev/null +++ b/release/MAC版本/js/spine-canvas-clipping.js @@ -0,0 +1,243 @@ +'use strict'; + +// The official spine-canvas SkeletonRenderer does not process clipping +// attachments. Keep its triangle rasterizer, but feed it geometry produced by +// SkeletonClipping so the viewer matches Spine's draw order and clipping rules. + +const QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; +const BLEND_MODES = ['source-over', 'lighter', 'multiply', 'screen']; +const unpremultipliedImages = new WeakMap(); + +function rendererConstructor(spine) { + return (spine.canvas && spine.canvas.SkeletonRenderer) || spine.SkeletonRenderer; +} + +function imageFromAttachment(attachment) { + const region = attachment && attachment.region; + // 4.0 stores the texture on the atlas page, while the other bundled + // runtimes expose it directly on the attachment region. + const renderRegion = region && region.renderObject; + const texture = region && (region.texture + || (region.page && region.page.texture) + || (renderRegion && renderRegion.texture) + || (renderRegion && renderRegion.page && renderRegion.page.texture)); + return texture && typeof texture.getImage === 'function' ? texture.getImage() : null; +} + +// Canvas 2D always applies source-alpha blending. A Spine texture exported +// with PMA already has RGB multiplied by alpha, so drawing it directly would +// multiply translucent edge pixels a second time. Convert it once to straight +// alpha and cache the result; Canvas can then blend it correctly. +function imageForCanvas(image, context, premultipliedAlpha) { + if (!premultipliedAlpha || !image || (typeof image !== 'object' && typeof image !== 'function')) return image; + const cached = unpremultipliedImages.get(image); + if (cached) return cached; + try { + const ownerDocument = context.canvas && context.canvas.ownerDocument; + const doc = ownerDocument || (typeof document !== 'undefined' ? document : null); + if (!image.width || !image.height) return image; + let canvas; + if (doc) canvas = doc.createElement('canvas'); + else { + try { canvas = require('@napi-rs/canvas').createCanvas(image.width, image.height); } + catch (e) { return image; } + } + canvas.width = image.width; + canvas.height = image.height; + const ctx = canvas.getContext('2d', { willReadFrequently: true }); + ctx.drawImage(image, 0, 0); + const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = pixels.data; + for (let i = 0; i < data.length; i += 4) { + const alpha = data[i + 3]; + if (alpha > 0 && alpha < 255) { + const factor = 255 / alpha; + data[i] = Math.min(255, Math.round(data[i] * factor)); + data[i + 1] = Math.min(255, Math.round(data[i + 1] * factor)); + data[i + 2] = Math.min(255, Math.round(data[i + 2] * factor)); + } + } + ctx.putImageData(pixels, 0, 0); + unpremultipliedImages.set(image, canvas); + return canvas; + } catch (e) { + // If pixel access is unavailable, retain the original texture so preview + // remains usable instead of failing the whole frame. + return image; + } +} + +function unpackVertices(vertices, count) { + const positions = new Array(count * 2); + const uvs = new Array(count * 2); + for (let i = 0, p = 0; i < count; i++, p += 2) { + const source = i * 8; + positions[p] = vertices[source]; + positions[p + 1] = vertices[source + 1]; + uvs[p] = vertices[source + 6]; + uvs[p + 1] = vertices[source + 7]; + } + return { positions, uvs }; +} + +function drawInterleaved(base, image, vertices, triangles, darkColor) { + for (let i = 0; i < triangles.length; i += 3) { + const a = triangles[i] * 8; + const b = triangles[i + 1] * 8; + const c = triangles[i + 2] * 8; + base.drawTriangle(image, + vertices[a], vertices[a + 1], vertices[a + 6], vertices[a + 7], + vertices[b], vertices[b + 1], vertices[b + 6], vertices[b + 7], + vertices[c], vertices[c + 1], vertices[c + 6], vertices[c + 7], + [...vertices.slice(a+2,a+6), ...vertices.slice(b+2,b+6), ...vertices.slice(c+2,c+6)], + darkColor ? Array.from({length:3}, () => [darkColor.r,darkColor.g,darkColor.b,0]).flat() : undefined); + } +} + +function createLegacyRenderer(spine, context) { + const Renderer = rendererConstructor(spine); + if (!Renderer || !spine.SkeletonClipping) throw new Error('Spine Canvas 渲染器不完整'); + const base = new Renderer(context); + base.triangleRendering = true; + base.premultipliedAlpha = false; + const clipper = new spine.SkeletonClipping(); + const dark = new spine.Color(0, 0, 0, 0); + + base.draw = function drawWithClipping(skeleton) { + const composite = context.globalCompositeOperation; + const drawOrder = skeleton.drawOrder; + const pma = !!base.premultipliedAlpha; + try { + for (let i = 0; i < drawOrder.length; i++) { + const slot = drawOrder[i]; + if (slot.bone && slot.bone.active === false) { + clipper.clipEndWithSlot(slot); + continue; + } + const attachment = slot.getAttachment(); + if (attachment instanceof spine.ClippingAttachment) { + clipper.clipStart(slot, attachment); + continue; + } + + try { + if (!attachment) continue; + let vertices; + let triangles; + let vertexCount; + if (attachment instanceof spine.RegionAttachment) { + vertices = base.computeRegionVertices(slot, attachment, false); + triangles = Renderer.QUAD_TRIANGLES || QUAD_TRIANGLES; + vertexCount = 4; + } else if (attachment instanceof spine.MeshAttachment) { + vertices = base.computeMeshVertices(slot, attachment, false); + triangles = attachment.triangles; + vertexCount = attachment.worldVerticesLength >> 1; + } else { + continue; + } + + const sourceImage = imageFromAttachment(attachment); + const image = base.gpuDrawing ? sourceImage : imageForCanvas(sourceImage, context, pma); + if (!image) continue; + context.globalAlpha = base.tempColor.a; + context.globalCompositeOperation = BLEND_MODES[slot.data.blendMode] || 'source-over'; + if (clipper.isClipping()) { + const unpacked = unpackVertices(vertices, vertexCount); + clipper.clipTriangles(unpacked.positions, unpacked.positions.length, + triangles, triangles.length, unpacked.uvs, base.tempColor, dark, false); + drawInterleaved(base, image, clipper.clippedVertices, clipper.clippedTriangles, slot.darkColor); + } else { + drawInterleaved(base, image, vertices, triangles, slot.darkColor); + } + } finally { + clipper.clipEndWithSlot(slot); + } + } + } finally { + clipper.clipEnd(); + context.globalAlpha = 1; + context.globalCompositeOperation = composite; + } + }; + base.clipper = clipper; + return base; +} + +// 3.4/3.5 predate clipping attachments and compute packed vertices on attachments. +function create34Renderer(spine, context) { + const base = new (rendererConstructor(spine))(context); + base.triangleRendering = true; + base.premultipliedAlpha = false; + base.draw = skeleton => { + const composite = context.globalCompositeOperation; + try { + for (const slot of skeleton.drawOrder) { + const attachment = slot.getAttachment(); + if (!(attachment instanceof spine.RegionAttachment) && !(attachment instanceof spine.MeshAttachment)) continue; + const vertices = attachment.updateWorldVertices(slot, false); + const sourceImage = imageFromAttachment(attachment); + const image = base.gpuDrawing ? sourceImage : imageForCanvas(sourceImage, context, base.premultipliedAlpha); + if (!image) continue; + context.globalAlpha = vertices[5]; + context.globalCompositeOperation = BLEND_MODES[slot.data.blendMode] || 'source-over'; + drawInterleaved(base, image, vertices, attachment instanceof spine.MeshAttachment ? attachment.triangles : QUAD_TRIANGLES); + } + } finally { context.globalAlpha = 1; context.globalCompositeOperation = composite; } + }; + return base; +} + +function create43Renderer(spine, context) { + const Renderer = rendererConstructor(spine); + if (!Renderer || !spine.SkeletonRendererCore) throw new Error('Spine 4.3 Canvas 渲染器不完整'); + const base = new Renderer(context); + base.triangleRendering = true; + base.premultipliedAlpha = false; + const core = new spine.SkeletonRendererCore(); + + base.draw = function drawWithCoreClipping(skeleton) { + const composite = context.globalCompositeOperation; + try { + const pma = !!base.premultipliedAlpha; + for (let command = core.render(skeleton, false); command; command = command.next) { + const sourceImage = command.texture && command.texture.getImage && command.texture.getImage(); + const image = base.gpuDrawing ? sourceImage : imageForCanvas(sourceImage, context, pma); + if (!image) continue; + context.globalAlpha = ((command.colors[0] >>> 24) & 255) / 255; + context.globalCompositeOperation = BLEND_MODES[command.blendMode] || 'source-over'; + const positions = command.positions; + const uvs = command.uvs; + const indices = command.indices; + for (let i = 0; i < command.numIndices; i += 3) { + const a = indices[i] * 2; + const b = indices[i + 1] * 2; + const c = indices[i + 2] * 2; + const unpack = packed => [((packed>>>16)&255)/255,((packed>>>8)&255)/255,(packed&255)/255,((packed>>>24)&255)/255]; + const colors = [a,b,c].flatMap(index => unpack(command.colors[index/2])); + const darkColors = [a,b,c].flatMap(index => unpack(command.darkColors[index/2])); + base.drawTriangle(image, + positions[a], positions[a + 1], uvs[a], uvs[a + 1], + positions[b], positions[b + 1], uvs[b], uvs[b + 1], + positions[c], positions[c + 1], uvs[c], uvs[c + 1], colors, darkColors); + } + } + } finally { + context.globalAlpha = 1; + context.globalCompositeOperation = composite; + } + }; + base.clipper = core.clipping; + return base; +} + +function createRenderer(spine, context, runtimeDir) { + const renderer = (runtimeDir === '3.4' || runtimeDir === '3.5') ? create34Renderer(spine, context) : runtimeDir === '4.3' + ? create43Renderer(spine, context) + : createLegacyRenderer(spine, context); + // Explicitly disable debug drawing in every supported runtime. + renderer.debugRendering = false; + return require('./spine-webgl-rasterizer.js').attach(renderer, context); +} + +module.exports = { createRenderer }; diff --git a/release/MAC版本/js/spine-legacy-binary.js b/release/MAC版本/js/spine-legacy-binary.js new file mode 100644 index 0000000..b016474 --- /dev/null +++ b/release/MAC版本/js/spine-legacy-binary.js @@ -0,0 +1,250 @@ +'use strict'; + +// Adapted from Esoteric Software's 3.4/3.5/3.6/3.7 spine-libgdx SkeletonBinary.java. +// Copyright (c) 2013-2019, Esoteric Software. See +// LICENSES/Spine-Legacy-Binary-License.txt for the original license notices. +// 3.4 source and license: LICENSES/Spine-3.4-License.txt. +// 3.5 source and license: LICENSES/Spine-3.5-License.txt. +// Decode the versioned wire format to an in-memory SkeletonJson object. The +// matching runtime builds attachments/timelines and applies loader.scale once. + +const dict = () => Object.create(null); +class Input { + constructor(bytes) { + if (!ArrayBuffer.isView(bytes)) throw new Error('骨骼二进制数据必须为字节数组'); + this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + this.offset = 0; + } + fail(message) { throw new Error('Spine 二进制解析失败(字节 ' + this.offset + '):' + message); } + need(n) { if (n < 0 || n > this.view.byteLength - this.offset) this.fail('文件截断或长度无效'); } + byte() { this.need(1); return this.view.getUint8(this.offset++); } + bool() { const b = this.byte(); if (b > 1) this.fail('无效布尔值'); return b === 1; } + float() { this.need(4); const v = this.view.getFloat32(this.offset); this.offset += 4; if (!Number.isFinite(v)) this.fail('无效浮点数'); return v; } + int() { this.need(4); const v = this.view.getInt32(this.offset); this.offset += 4; return v; } + varint(positive = true) { + let value = 0; + for (let shift = 0; shift <= 28; shift += 7) { + const b = this.byte(); + if (shift === 28 && (b & 240)) this.fail('无效变长整数'); + value |= (b & 127) << shift; + if (!(b & 128)) return positive ? value : ((value >>> 1) ^ -(value & 1)); + } + this.fail('无效变长整数'); + } + count() { const n = this.varint(); this.need(n); return n; } + string() { + const size = this.varint(); + if (size === 0) return null; + this.need(size - 1); + const end = this.offset + size - 1; + let result = ''; + // Old Spine exports use Java's 1/2/3-byte UTF-8 encoding of UTF-16 + // code units (including surrogate pairs), rather than string references. + while (this.offset < end) { + const b = this.byte(); + if (b < 128) result += String.fromCharCode(b); + else { + const extra = (b & 224) === 192 ? 1 : (b & 240) === 224 ? 2 : -1; + if (extra < 0 || this.offset + extra > end) this.fail('无效字符串'); + let code = b & (extra === 1 ? 31 : 15); + for (let i = 0; i < extra; i++) { const c = this.byte(); if ((c & 192) !== 128) this.fail('无效 UTF-8'); code = (code << 6) | (c & 63); } + result += String.fromCharCode(code); + } + } + return result; + } + color() { return (this.int() >>> 0).toString(16).padStart(8, '0'); } + floats(n) { this.need(n * 4); return Array.from({ length: n }, () => this.float()); } + shorts() { const n = this.count(); this.need(n * 2); return Array.from({ length: n }, () => { const v = this.view.getUint16(this.offset); this.offset += 2; return v; }); } + ref(list) { const i = this.varint(); if (i < 0 || i >= list.length) this.fail('索引越界:' + i); return list[i]; } +} + +function decode(bytes, runtimeDir) { + const r = new Input(bytes); + const skeleton = { hash: r.string(), spine: r.string() }; + if (!/^3\.[4567]\./.test(skeleton.spine || '')) r.fail('仅支持 Spine 3.4 / 3.5 / 3.6 / 3.7'); + const version = skeleton.spine.slice(0, 3); + if (runtimeDir && version !== runtimeDir) r.fail('骨骼版本与运行时不一致'); + const v37 = version === '3.7'; + const v34 = version === '3.4'; + const before36 = v34 || version === '3.5'; + skeleton.width = r.float(); skeleton.height = r.float(); + const nonessential = r.bool(); + if (nonessential) { if (!v34) skeleton.fps = r.float(); skeleton.images = r.string(); if (v37) skeleton.audio = r.string(); } + const root = { skeleton, bones: [], slots: [], ik: [], transform: [], path: [], skins: dict(), events: dict(), animations: dict() }; + const boneName = () => r.ref(root.bones).name; + const slotName = () => r.ref(root.slots).name; + const fields = (obj, names) => { for (const name of names.split(' ')) obj[name] = r.float(); return obj; }; + const boneList = () => Array.from({ length: r.count() }, boneName); + for (let i = 0, n = r.count(); i < n; i++) { + const b = { name: r.string() }; if (i) b.parent = boneName(); + fields(b, 'rotation x y scaleX scaleY shearX shearY length'); + if (v34) { b.inheritRotation = r.bool(); b.inheritScale = r.bool(); } + else b.transform = r.ref(['normal', 'onlyTranslation', 'noRotationOrReflection', 'noScale', 'noScaleOrReflection']); + if (nonessential) b.color = r.color(); root.bones.push(b); + } + for (let i = 0, n = r.count(); i < n; i++) { + const s = { name: r.string(), bone: boneName(), color: r.color() }; + if (!before36) { const dark = r.color(); if (dark !== 'ffffffff') s.dark = dark.slice(2); } + s.attachment = r.string(); s.blend = r.ref(['normal', 'additive', 'multiply', 'screen']); root.slots.push(s); + } + for (let i = 0, n = r.count(); i < n; i++) { + const c = { name: r.string(), order: v34 ? 0 : r.varint(), bones: boneList(), target: boneName(), mix: r.float(), bendPositive: r.byte() === 1 }; + if (v37) { c.compress = r.bool(); c.stretch = r.bool(); c.uniform = r.bool(); } root.ik.push(c); + } + for (let i = 0, n = r.count(); i < n; i++) { + const c = { name: r.string(), order: v34 ? 0 : r.varint(), bones: boneList(), target: boneName() }; + if (!before36) { c.local = r.bool(); c.relative = r.bool(); } + fields(c, 'rotation x y scaleX scaleY shearY rotateMix translateMix scaleMix shearMix'); root.transform.push(c); + } + for (let i = 0, n = r.count(); i < n; i++) { + const c = { name: r.string(), order: v34 ? 0 : r.varint(), bones: boneList(), target: slotName(), + positionMode: r.ref(['fixed', 'percent']), spacingMode: r.ref(['length', 'fixed', 'percent']), rotateMode: r.ref(['tangent', 'chain', 'chainScale']) }; + fields(c, 'rotation position spacing rotateMix translateMix'); root.path.push(c); + } + function vertices(n) { + if (!r.bool()) return r.floats(n * 2); + const out = []; + for (let i = 0; i < n; i++) { + const count = r.count(); if (!count) r.fail('加权顶点没有骨骼'); out.push(count); + for (let j = 0; j < count; j++) { const index = r.varint(); if (index < 0 || index >= root.bones.length) r.fail('顶点骨骼索引越界'); out.push(index, r.float(), r.float(), r.float()); } + } + return out; + } + function attachment(key) { + const a = { name: r.string() || key }; + const type = r.byte(); + if (before36 && type > 4) r.fail(version + ' 不支持此附件类型:' + type); + a.type = ['region', 'boundingbox', 'mesh', 'linkedmesh', 'path', 'point', 'clipping'][type]; + if (!a.type) r.fail('未知附件类型:' + type); + if (type === 0) { + a.path = r.string() || a.name; fields(a, 'rotation x y scaleX scaleY width height'); a.color = r.color(); + } else if (type === 2) { + a.path = r.string() || a.name; a.color = r.color(); const count = r.count(); + a.uvs = r.floats(count * 2); a.triangles = r.shorts(); + if (a.triangles.some(i => i >= count)) r.fail('网格三角形索引越界'); + a.vertices = vertices(count); a.hull = r.varint(); + if (nonessential) { a.edges = r.shorts(); fields(a, 'width height'); } + } else if (type === 3) { + a.path = r.string() || a.name; a.color = r.color(); const skin = r.string(); if (skin !== null) a.skin = skin; + a.parent = r.string(); a.deform = r.bool(); if (nonessential) fields(a, 'width height'); + } else if (type === 5) { + fields(a, 'rotation x y'); if (nonessential) a.color = r.color(); + } else { + if (type === 4) { a.closed = r.bool(); a.constantSpeed = r.bool(); } + if (type === 6) a.end = slotName(); + a.vertexCount = r.count(); a.vertices = vertices(a.vertexCount); + if (type === 4) a.lengths = r.floats(Math.floor(a.vertexCount / 3)); + if (nonessential) a.color = r.color(); + } + return a; + } + const skinNames = []; + function skin(name, isDefault = false) { + const count = r.count(); if (!count && isDefault) return; + const data = root.skins[name] = dict(); skinNames.push(name); + for (let i = 0; i < count; i++) { + const attachments = data[slotName()] = dict(); + for (let j = 0, n = r.count(); j < n; j++) { const key = r.string(); attachments[key] = attachment(key); } + } + } + skin('default', true); + for (let i = 0, n = r.count(); i < n; i++) skin(r.string()); + const eventNames = []; + for (let i = 0, n = r.count(); i < n; i++) { + const name = r.string(); eventNames.push(name); + const e = root.events[name] = { int: r.varint(false), float: r.float(), string: r.string() }; + if (v37) { e.audio = r.string(); if (e.audio !== null) fields(e, 'volume balance'); } + } + function curve(frame) { + const type = r.byte(); + if (type === 1) frame.curve = 'stepped'; + else if (type === 2) frame.curve = r.floats(4); + else if (type !== 0) r.fail('未知曲线类型:' + type); + } + function frames(read, curved = true) { + const count = r.count(); if (!count) r.fail('空时间线'); + return Array.from({ length: count }, (_, i) => { const frame = { time: r.float() }; read(frame); if (curved && i < count - 1) curve(frame); return frame; }); + } + function animation() { + const a = { slots: dict(), bones: dict(), ik: dict(), transform: dict(), paths: dict(), deform: dict() }; + for (let i = 0, n = r.count(); i < n; i++) { + const timelines = a.slots[slotName()] = dict(); + for (let j = 0, m = r.count(); j < m; j++) { + const type = r.byte(); + if (type === 0) timelines.attachment = frames(f => { f.name = r.string(); }, false); + else if (type === 1) timelines.color = frames(f => { f.color = r.color(); }); + else if (type === 2 && !before36) timelines.twoColor = frames(f => { f.light = r.color(); f.dark = r.color().slice(2); }); + else r.fail('未知插槽时间线'); + } + } + for (let i = 0, n = r.count(); i < n; i++) { + const timelines = a.bones[boneName()] = dict(); + for (let j = 0, m = r.count(); j < m; j++) { + const type = r.byte(), name = ['rotate', 'translate', 'scale', 'shear'][type]; + if (!name) r.fail('未知骨骼时间线'); + timelines[name] = frames(f => fields(f, type === 0 ? 'angle' : 'x y')); + } + } + for (let i = 0, n = r.count(); i < n; i++) { + const name = r.ref(root.ik).name; + a.ik[name] = frames(f => { f.mix = r.float(); f.bendPositive = r.byte() === 1; if (v37) { f.compress = r.bool(); f.stretch = r.bool(); } }); + } + for (let i = 0, n = r.count(); i < n; i++) { + const name = r.ref(root.transform).name; a.transform[name] = frames(f => fields(f, 'rotateMix translateMix scaleMix shearMix')); + } + for (let i = 0, n = r.count(); i < n; i++) { + const timelines = a.paths[r.ref(root.path).name] = dict(); + for (let j = 0, m = r.count(); j < m; j++) { + const type = r.byte(), name = ['position', 'spacing', 'mix'][type]; if (!name) r.fail('未知路径时间线'); + timelines[name] = frames(f => fields(f, type === 2 ? 'rotateMix translateMix' : name)); + } + } + for (let i = 0, n = r.count(); i < n; i++) { + const name = r.ref(skinNames), skinDeform = a.deform[name] = dict(); + for (let j = 0, m = r.count(); j < m; j++) { + const slot = slotName(), slotDeform = skinDeform[slot] = dict(); + for (let k = 0, q = r.count(); k < q; k++) { + const key = r.string(); + if (!root.skins[name][slot] || !root.skins[name][slot][key]) r.fail('变形附件不存在'); + slotDeform[key] = frames(f => { const length = r.count(); if (length) { f.offset = r.varint(); if (f.offset < 0 || f.offset > bytes.byteLength) r.fail('变形偏移越界'); f.vertices = r.floats(length); } }); + } + } + } + const drawCount = r.count(); + if (drawCount) a.drawOrder = Array.from({ length: drawCount }, () => { + const f = { time: r.float(), offsets: [] }; let previous = -1; + for (let i = 0, n = r.count(); i < n; i++) { + const index = r.varint(); const offset = r.varint(); + if (index <= previous || index >= root.slots.length || index + offset < 0 || index + offset >= root.slots.length) r.fail('绘制顺序索引越界'); + previous = index; f.offsets.push({ slot: root.slots[index].name, offset }); + } + return f; + }); + const eventCount = r.count(); + if (eventCount) a.events = Array.from({ length: eventCount }, () => { + const e = { time: r.float(), name: r.ref(eventNames), int: r.varint(false), float: r.float() }; + const data = root.events[e.name]; e.string = r.bool() ? r.string() : data.string; + if (v37 && data.audio !== null) fields(e, 'volume balance'); return e; + }); + return a; + } + for (let i = 0, n = r.count(); i < n; i++) { const name = r.string(); root.animations[name] = animation(); } + if (r.offset !== r.view.byteLength) r.fail('文件含未识别的尾部数据'); + return root; +} + +function install(spine, runtimeDir) { + if (!['3.4', '3.5', '3.6', '3.7'].includes(runtimeDir)) return spine; + if (runtimeDir === '3.4') spine.AtlasAttachmentLoader = spine.TextureAtlasAttachmentLoader; + spine.SkeletonBinary = class SkeletonBinary { + constructor(attachmentLoader) { this.attachmentLoader = attachmentLoader; this.scale = 1; } + readSkeletonData(bytes) { + const loader = new spine.SkeletonJson(this.attachmentLoader); loader.scale = this.scale; + return loader.readSkeletonData(decode(bytes, runtimeDir)); + } + }; + return spine; +} + +module.exports = { install, decode }; diff --git a/release/MAC版本/js/spine-preview-settings.js b/release/MAC版本/js/spine-preview-settings.js new file mode 100644 index 0000000..93b6e87 --- /dev/null +++ b/release/MAC版本/js/spine-preview-settings.js @@ -0,0 +1,58 @@ +'use strict'; + +// Eagle's item API has no arbitrary custom fields. Keep plugin metadata in +// userData, keyed by library + item ID, without editing Eagle metadata.json. +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +function identity(sourcePath, itemId) { + const directory = path.dirname(path.resolve(sourcePath)); + const match = path.basename(directory).match(/^(.+)\.info$/i); + return match + ? path.dirname(directory) + ':' + (itemId || match[1]) + : path.resolve(sourcePath); +} + +function createStore(userDataPath, sourcePath, itemId) { + const key = crypto.createHash('sha256').update(identity(sourcePath, itemId)).digest('hex'); + const directory = path.join(userDataPath, 'SpineViewer', 'preview-settings'); + const file = path.join(directory, key + '.json'); + return { + file, + read() { + try { + const data = JSON.parse(fs.readFileSync(file, 'utf8')); + return typeof data.premultipliedAlpha === 'boolean' ? data.premultipliedAlpha : undefined; + } catch (e) { + if (e.code === 'ENOENT') return undefined; + throw e; + } + }, + // This method is called only by the user's checkbox change event. + write(premultipliedAlpha) { + if (typeof premultipliedAlpha !== 'boolean') throw new TypeError('预乘设置必须为布尔值'); + fs.mkdirSync(directory, { recursive: true }); + const temp = file + '.' + crypto.randomBytes(8).toString('hex') + '.tmp'; + try { + fs.writeFileSync(temp, JSON.stringify({ premultipliedAlpha }, null, 2) + '\n', { flag: 'wx' }); + fs.renameSync(temp, file); + } finally { + try { fs.unlinkSync(temp); } catch (e) { if (e.code !== 'ENOENT') throw e; } + } + } + }; +} + +async function resolveDataPath(app) { + try { + const value = app && (app.userDataPath || (typeof app.getPath === 'function' && await app.getPath('userData'))); + if (typeof value === 'string' && value) return value; + } catch (e) { /* Some Eagle format-view windows reject app.getPath IPC. */ } + const home = require('os').homedir(); + if (process.platform === 'darwin') return path.join(home, 'Library', 'Application Support', 'Eagle'); + if (process.platform === 'win32') return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'Eagle'); + return path.join(process.env.XDG_CONFIG_HOME || path.join(home, '.config'), 'Eagle'); +} + +module.exports = { createStore, resolveDataPath }; diff --git a/release/MAC版本/js/spine-reconcile-worker.js b/release/MAC版本/js/spine-reconcile-worker.js new file mode 100644 index 0000000..e660029 --- /dev/null +++ b/release/MAC版本/js/spine-reconcile-worker.js @@ -0,0 +1,85 @@ +'use strict'; +const fs = require('fs'); +const path = require('path'); +const os = require('os'); +const crypto = require('crypto'); +const { spawn } = require('child_process'); +const utils = require('./spine-utils'); +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); + +function enqueue(src) { + const library = utils.findLibraryRoot(src); + if (!library) return; // Standalone tests/previews do not need Eagle refresh. + const key = crypto.createHash('sha256').update(__dirname + library).digest('hex'); + const directory = path.join(os.tmpdir(), 'spineviewer-reconcile', key); + fs.mkdirSync(directory, { recursive: true }); + const job = path.join(directory, crypto.createHash('sha256').update(src).digest('hex') + '.json'); + const temp = job + '.' + crypto.randomBytes(8).toString('hex') + '.tmp'; + fs.writeFileSync(temp, JSON.stringify({ src, deadline: Date.now() + 120000 })); + fs.renameSync(temp, job); + // Electron's Node mode runs the local worker without opening another Eagle. + const child = spawn(process.execPath, [__filename, directory], { + detached: true, stdio: 'ignore', env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' } + }); + child.on('error', error => { + try { fs.appendFileSync(path.join(__dirname, '../thumbnails.log'), '[worker] ' + String(error) + '\n'); } catch (_) {} + }); + child.unref(); +} + +async function run(directory) { + const lock = path.join(directory, 'worker.lock'); + let fd; + try { fd = fs.openSync(lock, 'wx'); } + catch (error) { + if (error.code !== 'EEXIST') throw error; + let pid; + try { pid = Number(fs.readFileSync(lock, 'utf8')); } catch (_) { return; } + if (!pid) return; // Another worker is still writing its lock. + try { process.kill(pid, 0); return; } catch (e) { if (e.code !== 'ESRCH') return; } + try { fs.unlinkSync(lock); } catch (_) { return; } + return run(directory); + } + fs.writeFileSync(fd, String(process.pid)); fs.closeSync(fd); + const snapshots = new Map(); + const nextChecks = new Map(); + const thumbnail = require('../thumbnail/spine'); + try { + let idle = 0; + while (idle < 2) { + await sleep(1000); // Allow the importing callback/window to finish. + const jobs = fs.readdirSync(directory).filter(name => name.endsWith('.json')); + if (!jobs.length) { idle++; continue; } + idle = 0; + for (const name of jobs) { + const file = path.join(directory, name); + let raw; + try { + raw = fs.readFileSync(file, 'utf8'); + const job = JSON.parse(raw); + if (Date.now() < (nextChecks.get(name) || 0)) continue; + const remaining = job.deadline - Date.now(); + nextChecks.set(name, Date.now() + (remaining > 110000 ? 1000 : remaining > 80000 ? 2500 : 5000)); + const result = Date.now() > job.deadline ? { complete: true } + : await thumbnail.reconcileOnce(job.src, snapshots.get(name)); + snapshots.set(name, result.signature); + if (result.complete && fs.readFileSync(file, 'utf8') === raw) { + fs.unlinkSync(file); snapshots.delete(name); nextChecks.delete(name); + } + } catch (error) { + if (error.code !== 'ENOENT') fs.appendFileSync(path.join(__dirname, '../thumbnails.log'), '[worker] ' + String(error) + '\n'); + } + } + } + } finally { + fs.unlinkSync(lock); + // Cover an enqueue racing the final idle check and lock release. + if (fs.readdirSync(directory).some(name => name.endsWith('.json'))) await run(directory); + } +} + +module.exports = { enqueue, run }; +if (require.main === module) run(process.argv[2]).catch(error => { + try { fs.appendFileSync(path.join(__dirname, '../thumbnails.log'), '[worker] ' + String(error) + '\n'); } catch (_) {} + process.exitCode = 1; +}); diff --git a/release/MAC版本/js/spine-render.js b/release/MAC版本/js/spine-render.js new file mode 100644 index 0000000..8721c80 --- /dev/null +++ b/release/MAC版本/js/spine-render.js @@ -0,0 +1,217 @@ +/** + * SpineViewer - 缩略图渲染模块(仅 Node 环境使用) + * 在纯 Node 中加载本地 Spine 运行时(通过 vm 注入到 global.spine), + * 使用 @napi-rs/canvas 光栅化骨骼的 setup pose / 首帧动画,输出 PNG buffer。 + */ +const fs = require('fs'); +const vm = require('vm'); +const path = require('path'); +const utils = require('./spine-utils.js'); +const spineBadge = require('./spine-badge.js'); + +let canvasLib = null; +try { + canvasLib = require('@napi-rs/canvas'); +} catch (e) { + canvasLib = null; +} + +let spineBadgePromise = null; + +/** 在缩略图右下角绘制官方 Spine badge,仅等比缩放,不改变官方图形。 */ +async function drawSpineBadge(ctx, width, height) { + if (!canvasLib || !ctx) return; + try { + if (!spineBadgePromise) { + spineBadgePromise = canvasLib.loadImage(spineBadge.path); + } + const badge = await spineBadgePromise; + const badgeSize = Math.max(44, Math.round(Math.min(width, height) * 0.15)); + const margin = Math.max(10, Math.round(badgeSize * 0.2)); + ctx.drawImage(badge, width - badgeSize - margin, height - badgeSize - margin, badgeSize, badgeSize); + } catch (e) { /* 缺少 badge 时不影响缩略图主体 */ } +} + +/** + * 在隔离的 vm 上下文中加载本地 Spine 运行时,返回 spine 命名空间对象。 + * 使用独立上下文可避免不同版本运行时的全局变量/类相互污染(例如 4.x 与 3.x + * 的 BinaryInput、DataView 等),因此不会跨版本混用。 + */ +function loadRuntime(dir) { + const code = fs.readFileSync(path.join(__dirname, '..', 'lib', dir, 'spine-canvas.js'), 'utf8'); + const sandbox = { + console, + setTimeout, + clearTimeout, + setInterval, + clearInterval, + performance: { now: () => Date.now() }, + }; + // 部分运行时通过 window/self/globalThis 访问全局 + sandbox.window = sandbox; + sandbox.self = sandbox; + sandbox.globalThis = sandbox; + vm.createContext(sandbox); + vm.runInContext(code, sandbox, { filename: 'lib/' + dir + '/spine-canvas.js' }); + return require('./spine-legacy-binary.js').install(sandbox.spine, dir); +} + +/** 构造 TextureAtlas 并挂载贴图(跨版本兼容)。 + * texturePaths: { atlas 中引用的贴图名 -> 绝对路径 },用于跨 Eagle item 文件夹解析贴图。 + */ +function buildTextureAtlas(spine, atlasText, dir, texturePaths) { + if (!canvasLib) throw new Error('@napi-rs/canvas 不可用'); + return new Promise((resolve, reject) => { + (async () => { + // 解析所有页面贴图名,并预先异步加载 + let pageNames = []; + try { pageNames = utils.parseAtlasPages(atlasText); } catch (e) { pageNames = []; } + + const textureMap = {}; + await Promise.all(pageNames.map(async (name) => { + // 优先使用跨文件夹解析出的绝对路径,否则回退到 atlas 同目录 + const p = (texturePaths && texturePaths[name]) ? texturePaths[name] : path.join(dir, name); + if (!fs.existsSync(p)) return; + try { + const img = await canvasLib.loadImage(p); + textureMap[name] = img; + } catch (e) { /* ignore */ } + })); + + const makeTexture = (name) => { + let img = textureMap[name]; + if (!img) { + // 找不到图片时用 2x2 灰色占位纹理 + const c = canvasLib.createCanvas(2, 2); + const cx = c.getContext('2d'); + cx.fillStyle = '#888888'; + cx.fillRect(0, 0, 2, 2); + img = c; + } + if (spine.CanvasTexture) return new spine.CanvasTexture(img); + if (spine.canvas && spine.canvas.CanvasTexture) return new spine.canvas.CanvasTexture(img); + return new spine.Texture(img); + }; + + let atlas; + const is4x = typeof spine.TextureAtlas === 'function' && spine.TextureAtlas.length <= 1; + if (is4x) { + atlas = new spine.TextureAtlas(atlasText); + for (const page of atlas.pages) { + const tex = makeTexture(page.name); + if (page.setTexture) page.setTexture(tex); + else page.texture = tex; + } + } else { + atlas = new spine.TextureAtlas(atlasText, (name) => makeTexture(name)); + } + resolve(atlas); + })().catch(reject); + }); +} + +/** 读取骨骼数据(json 或二进制) */ +function readSkeletonData(spine, skeletonPath, atlas, isBinary) { + const atlasLoader = new spine.AtlasAttachmentLoader(atlas); + if (isBinary) { + const loader = new spine.SkeletonBinary(atlasLoader); + loader.scale = 1; + const buf = fs.readFileSync(skeletonPath); + return loader.readSkeletonData(new Uint8Array(buf)); + } else { + const loader = new spine.SkeletonJson(atlasLoader); + loader.scale = 1; + const text = fs.readFileSync(skeletonPath, 'utf8'); + return loader.readSkeletonData(text); + } +} + +/** 计算包围盒(跨版本兼容) */ +function getBounds(spine, skeleton) { + try { + if (skeleton.getBoundsRect) { + const r = skeleton.getBoundsRect(); + if (r && r.width !== undefined) return { x: r.x, y: r.y, width: r.width, height: r.height }; + } + if (skeleton.getBounds) { + const offset = new spine.Vector2(); + const size = new spine.Vector2(); + skeleton.getBounds(offset, size, []); + if (size.x > 0 || size.y > 0) return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + } catch (e) { /* ignore */ } + return null; +} + +/** + * 渲染首帧动画到 PNG buffer。 + * @returns {Promise} + */ +async function renderThumbnail({ skeletonPath, atlasPath, texturePaths, version, runtimeDir, size = 400 }) { + if (!canvasLib) throw new Error('@napi-rs/canvas 不可用'); + const isBinary = /\.skel(\.bytes)?$/i.test(skeletonPath); + const dir = path.dirname(skeletonPath); + const atlasText = fs.readFileSync(atlasPath, 'utf8'); + const premultipliedAlpha = utils.parseAtlasPma(atlasText) === true; + + const spine = loadRuntime(runtimeDir); + const atlas = await buildTextureAtlas(spine, atlasText, dir, texturePaths); + const skeletonData = readSkeletonData(spine, skeletonPath, atlas, isBinary); + + if (!skeletonData || !skeletonData.bones || skeletonData.bones.length === 0) { + const name = path.basename(skeletonPath); + throw new Error('骨骼数据为空:' + name); + } + const skeleton = new spine.Skeleton(skeletonData); + utils.applySkin(skeleton, utils.preferredSkin(skeletonData)); + + // 计算所有动画的包围盒,取最合适的姿态用于缩略图。 + // 默认使用 setup pose(编辑器内的标准站姿),保证缩略图稳定、接近编辑视图。 + let bounds = null; + if (skeleton.setToSetupPose) skeleton.setToSetupPose(); + if (skeleton.updateWorldTransform) { + if (spine.Physics && spine.Physics.update !== undefined) skeleton.updateWorldTransform(spine.Physics.update); + else skeleton.updateWorldTransform(); + } + bounds = getBounds(spine, skeleton); + + const cw = size, ch = size; + const canvas = canvasLib.createCanvas(cw, ch); + const ctx = canvas.getContext('2d'); + ctx.fillStyle = '#1e1e1e'; + ctx.fillRect(0, 0, cw, ch); + + if (bounds && bounds.width > 0 && bounds.height > 0) { + const pad = 0.1; + const scale = Math.min((cw * (1 - pad * 2)) / bounds.width, (ch * (1 - pad * 2)) / bounds.height); + // Spine 世界坐标 Y 轴向上,而 Canvas 2D Y 轴向下,需翻转 Y。 + const cx = bounds.x + bounds.width / 2; + const cy = bounds.y + bounds.height / 2; + ctx.save(); + ctx.translate(cw / 2, ch / 2); + ctx.scale(scale, -scale); + ctx.translate(-cx, -cy); + + let renderer = null; + try { renderer = require('./spine-canvas-clipping.js').createRenderer(spine, ctx, runtimeDir); } + catch (e) { + if (spine.canvas && spine.canvas.SkeletonRenderer) renderer = new spine.canvas.SkeletonRenderer(ctx); + else if (spine.SkeletonRenderer) renderer = new spine.SkeletonRenderer(ctx); + } + if (renderer) { + // 使用三角渲染,正确处理 mesh 附件(如角色身体的网格) + if ('triangleRendering' in renderer) renderer.triangleRendering = true; + renderer.premultipliedAlpha = premultipliedAlpha; + renderer.draw(skeleton); + if (renderer.dispose) renderer.dispose(); + } + ctx.restore(); + } + + await drawSpineBadge(ctx, cw, ch); + spineBadge.drawVersion(ctx, cw, ch, skeletonData.version || version); + const buf = canvas.toBuffer('image/png'); + return buf; +} + +module.exports = { renderThumbnail, loadRuntime, buildTextureAtlas, readSkeletonData, getBounds, drawSpineBadge, canvasLib }; diff --git a/release/MAC版本/js/spine-utils.js b/release/MAC版本/js/spine-utils.js new file mode 100644 index 0000000..c2d2cee --- /dev/null +++ b/release/MAC版本/js/spine-utils.js @@ -0,0 +1,714 @@ +/** + * SpineViewer - 工具模块 + * 该模块为纯 Node.js CommonJS,供 viewer/thumbnail 复用。 + * 职责: + * - 识别 Spine 导出文件的类型(skel/skel.bytes/json/atlas/atlas.txt/png/jpg/jpeg/webp) + * - 在同一个目录内自动关联配套的骨骼文件、atlas、贴图 + * - 从骨骼数据中检测 Spine 版本 + * - 根据版本选择合适的本地运行时 + */ + +const fs = require('fs'); +const path = require('path'); + +const SKELETON_EXTS = ['.skel', '.skel.bytes', '.json']; +const ATLAS_EXTS = ['.atlas', '.atlas.txt']; +const TEXTURE_EXTS = ['.png', '.jpg', '.jpeg', '.webp']; +const ALL_EXTS = SKELETON_EXTS.concat(ATLAS_EXTS, TEXTURE_EXTS); +const fileIndexCache = new Map(); +const skeletonJsonCache = new Map(); +const JSON_PROBE_BYTES = 256 * 1024; + +// Spine 导出常见的后缀,匹配时归一化掉 +const SUFFIX_RE = /-(pro|ess|pma|base|atlas|_pma|_pro|_ess)$/i; + +function extOf(name) { + const lower = name.toLowerCase(); + for (let i = 0; i < SKELETON_EXTS.length; i++) { + if (lower.endsWith(SKELETON_EXTS[i])) return SKELETON_EXTS[i]; + } + for (let i = 0; i < ATLAS_EXTS.length; i++) { + if (lower.endsWith(ATLAS_EXTS[i])) return ATLAS_EXTS[i]; + } + for (let i = 0; i < TEXTURE_EXTS.length; i++) { + if (lower.endsWith(TEXTURE_EXTS[i])) return TEXTURE_EXTS[i]; + } + return null; +} + +function isSkeletonFile(name) { + const ext = extOf(name); + return ext === '.skel' || ext === '.skel.bytes' || ext === '.json'; +} + +function isAtlasFile(name) { + const ext = extOf(name); + return ext === '.atlas' || ext === '.atlas.txt'; +} + +function isTextureFile(name) { + const ext = extOf(name); + return TEXTURE_EXTS.indexOf(ext) !== -1; +} + +/** 去掉文件名中的扩展名 */ +function stemOf(name) { + const ext = extOf(name); + if (!ext) return name; + return name.slice(0, name.length - ext.length); +} + +/** 归一化 stem,去掉 Spine 常见后缀,用于跨文件匹配 */ +function normalizeStem(name) { + return stemOf(name).toLowerCase().replace(SUFFIX_RE, ''); +} + +/** 从 JSON 文本中读取 spine 版本 */ +function detectVersionFromJson(text) { + try { + const json = JSON.parse(text); + if (json && json.skeleton && json.skeleton.spine) { + return String(json.skeleton.spine); + } + } catch (e) { /* ignore */ } + return null; +} + +/** 从二进制数据中读取 spine 版本(扫描前若干字节中的版本号) */ +function detectVersionFromBuffer(buf) { + let s = ''; + const bytes = new Uint8Array(buf); + const len = Math.min(bytes.length, 160); + for (let i = 0; i < len; i++) { + s += String.fromCharCode(bytes[i]); + } + const m = s.match(/(\d+\.\d+(?:\.\d+)?)/); + return m ? m[1] : null; +} + +/** 从文件读取 spine 版本 */ +function detectVersion(filePath) { + const lower = filePath.toLowerCase(); + if (lower.endsWith('.json')) { + return detectVersionFromJson(fs.readFileSync(filePath, 'utf8')); + } + return detectVersionFromBuffer(fs.readFileSync(filePath)); +} + +/** + * 根据检测到的版本与文件类型,选择本地运行时目录。 + * - 3.4–3.7 二进制通过本地兼容解析器加载,始终使用对应版本运行时 + */ +function chooseRuntimeDir(version, isBinary) { + if (!version) return null; + const major = parseInt(version.split('.')[0], 10); + if (major === 3) { + const minor = parseFloat(version); + if (minor === 3.4) return '3.4'; + if (minor === 3.5) return '3.5'; + if (minor <= 3.6) return '3.6'; + if (minor <= 3.7 + 0.0001) return '3.7'; + return '3.8'; + } else if (major === 4) { + const minor = parseFloat(version); + if (minor <= 4.0 + 0.0001) return '4.0'; + if (minor <= 4.1 + 0.0001) return '4.1'; + if (minor <= 4.2 + 0.0001) return '4.2'; + return '4.3'; + } + return null; +} + +/** + * 快速区分 Spine JSON、普通 JSON 和仍在写入的 JSON。 + * 仅以 Spine 官方导出的 `skeleton.spine` 版本字段作为肯定标识;bones/slots 等 + * 通用字段不能证明文件来自 Spine。大文件只探测前 256KB。 + */ +function classifySkeletonJson(filePath) { + try { + const stat = fs.statSync(filePath); + if (!stat.isFile() || stat.size === 0) return 'pending'; + const signature = stat.size + ':' + Math.round(stat.mtimeMs); + const cached = skeletonJsonCache.get(filePath); + if (cached && cached.signature === signature) return cached.kind; + + const length = Math.min(stat.size, JSON_PROBE_BYTES); + const fd = fs.openSync(filePath, 'r'); + const buffer = Buffer.allocUnsafe(length); + try { fs.readSync(fd, buffer, 0, length, 0); } finally { fs.closeSync(fd); } + const text = buffer.toString('utf8'); + const hasSkeletonKey = /"skeleton"\s*:/i.test(text); + const versionMatch = text.match(/"skeleton"\s*:\s*\{[\s\S]{0,8192}?"spine"\s*:\s*"(\d+\.\d+(?:\.\d+)?(?:[^"\\]|\\.)*)"/i); + let kind; + if (versionMatch) { + kind = 'spine'; + } else if (stat.size > JSON_PROBE_BYTES) { + kind = 'other'; + } else { + try { + JSON.parse(text); + kind = 'other'; + } catch (e) { + // 只有已经出现 skeleton 键但文件尚未完整写入时才继续短暂等待。 + // JSONC、配置文件或损坏的普通 JSON 不应进入 Spine 补刷流程。 + kind = hasSkeletonKey ? 'pending' : 'other'; + } + } + + if (skeletonJsonCache.size > 2048) skeletonJsonCache.clear(); + skeletonJsonCache.set(filePath, { signature, kind }); + return kind; + } catch (e) { + return 'pending'; + } +} + +function looksLikeSkeletonJson(filePath) { + return classifySkeletonJson(filePath) === 'spine'; +} + +/** 文件修改时间(毫秒) */ +function mtimeOf(fp) { + try { return fs.statSync(fp).mtimeMs; } catch (e) { return 0; } +} + +/** 读取某 item 元数据里的创建时间 btime(毫秒),用于按“同一批导入”配对 */ +function btimeOf(fp) { + const d = itemMeta(path.dirname(fp)); + return (d && d.btime) || 0; +} + +/** + * Eagle item 的实际入库时间。 + * metadata.json 的 birthtime 在生成缩略图、修改标签后也不会改变,比素材自身的 + * btime/mtime 更适合判断多个独立 .info 项是否来自同一次拖入。 + */ +function importTimeOf(fp) { + try { + const metaPath = path.join(path.dirname(fp), 'metadata.json'); + const stat = fs.statSync(metaPath); + return stat.birthtimeMs || stat.ctimeMs || stat.mtimeMs || 0; + } catch (e) { + return btimeOf(fp); + } +} + +/** 骨骼版本所属家族(3x / 4x),atlas 格式按版本家族区分 */ +function versionFamily(version) { + if (!version) return null; + const major = parseInt(version.split('.')[0], 10); + return major <= 3 ? '3x' : '4x'; +} + +/** 根据 atlas 文本判断其格式家族(3x / 4x) */ +function atlasFamily(atlasText) { + if (!atlasText) return null; + // 4.x atlas 用 `bounds:` 定义区域;3.x 用 `xy:`/`size:`/`orig:`/`offset:`。 + // 注意:`scale:` 在 3.x 也会出现(如字体缩放),不能单独作为 4x 依据。 + // 因此以 `bounds:` 作为最可靠的 4.x 标志;若整体含 `xy:` 判定为 3x。 + if (/\bbounds\s*:/.test(atlasText)) return '4x'; + if (/\bxy\s*:/.test(atlasText)) return '3x'; + return '3x'; +} + +/** 读取某 item 文件夹的 metadata.json(含 folders、isDeleted、btime 等) */ +function itemMeta(itemDir) { + if (!itemDir) return null; + try { + return JSON.parse(fs.readFileSync(path.join(itemDir, 'metadata.json'), 'utf8')); + } catch (e) { + return null; + } +} + +/** 读取某个资产文件所属 item 文件夹的 Eagle 逻辑文件夹 id 列表 */ +function foldersOfItem(filePath) { + const d = itemMeta(path.dirname(filePath)); + return d && Array.isArray(d.folders) ? d.folders : []; +} + +/** 判断某 item 是否已被放入 Eagle 回收站(isDeleted) */ +function isItemDeleted(filePath) { + const d = itemMeta(path.dirname(filePath)); + return !!(d && d.isDeleted); +} + +/** 从任意 item 路径向上定位 Eagle 库根目录 */ +function findLibraryRoot(filePath) { + let dir = path.dirname(filePath); // item 文件夹 + for (let i = 0; i < 8; i++) { + const parent = path.dirname(dir); + if (parent === dir) break; + try { + if (fs.existsSync(path.join(parent, 'metadata.json')) && fs.existsSync(path.join(parent, 'images'))) { + return parent; + } + } catch (e) { /* ignore */ } + dir = parent; + } + return null; +} + +/** 解析库根 metadata.json,返回 { folderId -> children[] } 及文件夹名 */ +function readFolderInfo(libRoot) { + const map = {}; + const names = {}; + if (!libRoot) return { map, names }; + try { + const d = JSON.parse(fs.readFileSync(path.join(libRoot, 'metadata.json'), 'utf8')); + const folders = d.folders || []; + for (const f of folders) { + if (!f) continue; + map[f.id] = Array.isArray(f.children) ? f.children : []; + names[f.id] = f.name || ''; + } + } catch (e) { /* ignore */ } + return { map, names }; +} + +/** + * 计算允许匹配的 Eagle 文件夹 id 集合: + * 仅包含「选中文件所在的文件夹」本身,不下钻子文件夹,也不匹配父级/兄弟文件夹。 + */ +function getValidFolders(filePath) { + const itemFolders = foldersOfItem(filePath); + if (itemFolders.length === 0) return null; // 未归入任何 Eagle 文件夹,则不限定 + return new Set(itemFolders); +} + +/** 判断目录是否为 Eagle 的 item 元数据文件夹(包含 metadata.json) */ +function isEagleItemDir(dir) { + try { return fs.existsSync(path.join(dir, 'metadata.json')); } catch (e) { return false; } +} + +/** + * 计算需要搜索的目录列表。 + * Eagle 会把导入的每个文件拆分成独立的元数据文件夹(如 `images/.info/`), + * 因此配套的骨骼/atlas/贴图可能位于不同的 item 文件夹中。 + * 返回:当前 item 文件夹 + 其同级的所有 item 文件夹。 + */ +function getSearchRoots(filePath) { + const roots = []; + const itemDir = path.dirname(filePath); + roots.push(itemDir); + if (isEagleItemDir(itemDir)) { + const parent = path.dirname(itemDir); + try { + for (const name of fs.readdirSync(parent)) { + const sub = path.join(parent, name); + try { + if (fs.statSync(sub).isDirectory() && isEagleItemDir(sub)) { + roots.push(sub); + } + } catch (e) { /* ignore */ } + } + } catch (e) { /* ignore */ } + } + return [...new Set(roots)]; +} + +/** 把库根目录 images/ 下所有 item 文件夹加入搜索根(去重)。 + * 用于覆盖同伴位于不同 .info / 跨批次的情况(全库兜底)。 */ +function buildRootsWithLibraryRoot(filePath, roots) { + const libRoot = findLibraryRoot(filePath); + if (!libRoot) return; + const imagesDir = path.join(libRoot, 'images'); + try { + if (!fs.existsSync(imagesDir)) return; + for (const name of fs.readdirSync(imagesDir)) { + const sub = path.join(imagesDir, name); + try { + if (fs.statSync(sub).isDirectory() && isEagleItemDir(sub)) { + if (roots.indexOf(sub) === -1) roots.push(sub); + } + } catch (e) { /* ignore */ } + } + } catch (e) { /* ignore */ } +} + +/** + * 在多个目录中收集所有 Spine 相关文件,返回 [{ name, fullPath }]。 + * 若传入 validFolders(Eagle 逻辑文件夹 id 集合),则只保留位于这些文件夹内的 item, + * 从而把匹配范围限定在「选中文件所在的 Eagle 文件夹及其子文件夹」内。 + */ +function collectSpineFiles(roots, validFolders) { + const seen = new Set(); + const out = []; + for (const root of roots) { + let entries; + try { entries = fs.readdirSync(root); } catch (e) { continue; } + for (const name of entries) { + const full = path.join(root, name); + try { if (!fs.statSync(full).isFile()) continue; } catch (e) { continue; } + if (!extOf(name)) continue; // 只关心 Spine 相关扩展 + // 排除 Eagle 回收站中已删除的项 + if (isItemDeleted(full)) continue; + if (validFolders && validFolders.size) { + const itemFolders = foldersOfItem(full); + if (!itemFolders.some((f) => validFolders.has(f))) continue; // 不在允许的文件夹内 + } + if (seen.has(full)) continue; + seen.add(full); + out.push({ name, fullPath: full }); + } + } + return out; +} + +/** + * 缩略图批量生成时,同一时刻会有很多 atlas/json/skel 回调。对全库文件清单做一个 + * 很短的缓存,下一轮轮询仍会重新扫描,因此既降低大文件夹导入开销,也不会漏掉 + * 正在落盘的新文件。 + */ +function collectSpineFilesCached(filePath, roots, refresh) { + const libRoot = findLibraryRoot(filePath); + // Outside an Eagle library, sibling asset folders are independent search + // scopes. Sharing their parent as a cache key can return another skeleton. + const key = libRoot || JSON.stringify([...roots].sort()); + const now = Date.now(); + const cached = fileIndexCache.get(key); + if (!refresh && cached && now - cached.time < 1500) return cached.files; + const files = collectSpineFiles(roots, null); + fileIndexCache.set(key, { time: now, files }); + return files; +} + +/** + * 修正不可靠的源路径。 + * Eagle 传给缩略图 handler 的 src 有时指向一个已清理/不存在的 `.info` 目录 + * (例如其内部临时工作目录)。此时按文件名在整个库 images/ 下找到真实存在的 + * 源文件,作为后续资源发现的基准。 + */ +function resolveRealSource(filePath) { + // 源目录存在且是有效 item 目录 → 直接用 + const dir = path.dirname(filePath); + if (isEagleItemDir(dir)) return filePath; + const name = path.basename(filePath); + const libRoot = findLibraryRoot(filePath); + if (!libRoot) return filePath; + const imagesDir = path.join(libRoot, 'images'); + try { + if (!fs.existsSync(imagesDir)) return filePath; + // 优先找“文件名 + 类型”匹配的真实文件。若存在同名文件,返回它所在目录, + // 以便后续 getSearchRoots/selectBest 能借助其 folders/btime 精确匹配。 + let fallback = null; + for (const d of fs.readdirSync(imagesDir)) { + const sub = path.join(imagesDir, d); + if (!isEagleItemDir(sub)) continue; + const cand = path.join(sub, name); + if (fs.existsSync(cand)) { + // 优先选择未被删除的项 + if (!isItemDeleted(cand)) return cand; + if (!fallback) fallback = cand; + } + } + if (fallback) return fallback; + } catch (e) { /* ignore */ } + return filePath; +} + +/** + * 发现与所选文件 related 的 Spine 资源(跨 Eagle 多个 item 文件夹)。 + * 返回 { skeletonPath, atlasPath, texturePaths, base, isBinary, ... } + * - texturePaths: { atlas 中引用的贴图名 -> 绝对路径 } + */ +function discoverAssets(filePath, options) { + options = options || {}; + const strictStem = !!options.strictStem; + const requestedCrossBatch = !!options.allowCrossBatch; + const maxCrossBatchDeltaMs = Math.max(30000, Number(options.maxCrossBatchDeltaMs) || 5 * 60 * 1000); + filePath = resolveRealSource(filePath); + const selected = path.basename(filePath); + const selectedStem = normalizeStem(selected); + // 先扫码“选中 item 文件夹 + 同级所有 .info”(精确、不跨批次)。 + const roots = getSearchRoots(filePath); + // 若同级范围无法凑齐骨架+图集(常见于 Eagle 导入瞬间,同伴落在别的 .info), + // 则扩展搜索到整个库的 images/ 目录(全库兜底,靠“同家族 + 同文件夹 + 最近 btime”配对)。 + buildRootsWithLibraryRoot(filePath, roots); + + // 导入时 Eagle 会先创建各个 .info,再异步写 folders。严格模式必须把尚未写入 + // folders 的同批资源也纳入候选,之后用 metadata.json 的 birthtime 精确配对。 + const validFolders = getValidFolders(filePath); + // 导入瞬间 folders 可能尚未写入。没有明确 Eagle 文件夹 ID 时禁止跨批次, + // 否则单独导入的同名 JSON 会借用库中任意旧 atlas 生成错误缩略图。 + const allowCrossBatch = requestedCrossBatch && !!(validFolders && validFolders.size); + const allowedImportDelta = allowCrossBatch ? maxCrossBatchDeltaMs : 30000; + let files = collectSpineFiles(roots, validFolders); + if (strictStem) { + const allFiles = collectSpineFilesCached(filePath, roots, options.refreshIndex); + if (allowCrossBatch && validFolders && validFolders.size) { + files = allFiles.filter((f) => foldersOfItem(f.fullPath).some((id) => validFolders.has(id))); + } else { + files = allFiles; + } + } + + let skeletonFiles = files.filter((f) => isSkeletonFile(f.name)); + const atlasFiles = files.filter((f) => isAtlasFile(f.name)); + const textureFiles = files.filter((f) => isTextureFile(f.name)); + // 导入缩略图始终按同名资源链匹配。先按 stem 缩小候选,再检查 JSON 内容, + // 避免每个回调都解析库中所有普通 JSON。 + if (strictStem) { + skeletonFiles = skeletonFiles.filter((f) => normalizeStem(f.name) === selectedStem); + } + + // 区分“骨架 json”和“普通 json”:只保留形似骨架的 json + const realSkeletonFiles = skeletonFiles.filter((f) => { + if (f.name.toLowerCase().endsWith('.json')) return looksLikeSkeletonJson(f.fullPath); + return true; + }); + + // 工具:优先选择与 refFile 同一批入库的候选,再看 Eagle 逻辑文件夹及素材时间。 + // 这可区分同一文件夹中多次导入的同名 Spine 导出,又不受素材原始时间影响。 + const selectBest = (cands, refFile) => { + if (!cands || cands.length === 0) return null; + const refFolders = foldersOfItem(refFile); + const refImportTime = importTimeOf(refFile); + const refBtime = btimeOf(refFile); + const ranked = cands.map((c) => { + const cFolders = foldersOfItem(c.fullPath); + return { + c, + importDelta: refImportTime ? Math.abs(importTimeOf(c.fullPath) - refImportTime) : Number.MAX_SAFE_INTEGER, + sameFolder: refFolders.length && cFolders.some((f) => refFolders.indexOf(f) !== -1) ? 1 : 0, + btimeDelta: refBtime ? Math.abs(btimeOf(c.fullPath) - refBtime) : Number.MAX_SAFE_INTEGER, + }; + }); + ranked.sort((a, b) => allowCrossBatch + ? (b.sameFolder - a.sameFolder || a.importDelta - b.importDelta || a.btimeDelta - b.btimeDelta || a.c.fullPath.localeCompare(b.c.fullPath)) + : (a.importDelta - b.importDelta || b.sameFolder - a.sameFolder || a.btimeDelta - b.btimeDelta || a.c.fullPath.localeCompare(b.c.fullPath)) + ); + return ranked[0].c; + }; + + // 辅助:读取候选 atlas 的格式家族,以及候选骨骼的版本家族 + const familyOfAtlas = (f) => { try { return atlasFamily(fs.readFileSync(f.fullPath, 'utf8')); } catch (e) { return null; } }; + const familyOfSkel = (f) => { try { return versionFamily(detectVersion(f.fullPath)); } catch (e) { return null; } }; + + // 选中的文件若是 atlas,则读取其格式家族,用于匹配同家族的骨骼 + const selectedAtlasFamily = isAtlasFile(selected) + ? (() => { try { return atlasFamily(fs.readFileSync(filePath, 'utf8')); } catch (e) { return null; } })() + : null; + + // 1) 骨骼文件 + let skeleton = null; + // 若选中的就是骨骼文件,务必使用它本身(它的版本即最终版本) + if (isSkeletonFile(selected)) { + skeleton = realSkeletonFiles.find((f) => f.fullPath === filePath) || + realSkeletonFiles.find((f) => f.name === selected) || null; + } + if (!skeleton) { + // 依选中 stem 匹配;优先与选中 atlas 同家族(3x/4x),再按同文件夹/同批导入 + let cands = realSkeletonFiles.filter((f) => normalizeStem(f.name) === selectedStem); + if (selectedAtlasFamily && cands.length > 1) { + const same = cands.filter((f) => familyOfSkel(f) === selectedAtlasFamily); + if (same.length > 0) cands = same; + } + skeleton = cands.length > 0 ? selectBest(cands, filePath) : null; + } + if (!skeleton && realSkeletonFiles.length > 0) { + if (strictStem) { + skeleton = null; + } else { + // 忽略 stem:优先与选中 atlas 同家族,再按入库批次选取 + let cands = realSkeletonFiles; + if (selectedAtlasFamily) { + const same = cands.filter((f) => familyOfSkel(f) === selectedAtlasFamily); + if (same.length > 0) cands = same; + } + skeleton = selectBest(cands, filePath); + } + } + + + // 2) atlas 文件 —— 优先与骨骼版本家族一致(3x/4x),避免 3.8 骨骼配 4x atlas + let atlas = null; + if (isAtlasFile(selected)) { + atlas = atlasFiles.find((f) => f.fullPath === filePath) || + atlasFiles.find((f) => f.name === selected) || null; + } + // 统一的候选选择:优先“与骨骼同家族(3x/4x)”的 atlas,再按“同文件夹 + 最近 btime”挑选。 + // 家族过滤无条件优先,避免 4x 骨骼配到 3x 图集(会导致 UV/坐标错乱)。 + const pickAtlas = (cands, refFile) => { + if (!cands || cands.length === 0) return null; + const skelFamily = skeleton ? familyOfSkel(skeleton) : null; + if (skelFamily) { + const same = cands.filter((f) => familyOfAtlas(f) === skelFamily); + if (same.length > 0) cands = same; + } + return selectBest(cands, refFile); + }; + + if (!atlas) { + let cands = atlasFiles.filter((f) => normalizeStem(f.name) === selectedStem); + atlas = pickAtlas(cands, filePath); + } + if (!atlas && skeleton) { + const skelStem = normalizeStem(skeleton.name); + let cands = atlasFiles.filter((f) => normalizeStem(f.name) === skelStem); + atlas = pickAtlas(cands, skeleton.fullPath); + } + if (!atlas && skeleton) { + if (strictStem) { + atlas = null; + } else { + // 忽略 stem:用与骨骼同家族且同批入库的 atlas + atlas = pickAtlas(atlasFiles, skeleton.fullPath); + } + } + if (!atlas && !strictStem && atlasFiles.length === 1) atlas = atlasFiles[0]; + + // 严格模式用于导入缩略图:配套骨骼和图集应由同一次拖入创建。若时间差 + // 过大,说明新同伴还没落盘,返回缺失让调用方继续等待,不能借用旧同名资源。 + if (strictStem && skeleton && atlas) { + const pairDelta = Math.abs(importTimeOf(skeleton.fullPath) - importTimeOf(atlas.fullPath)); + if (pairDelta > allowedImportDelta) { + if (isAtlasFile(selected)) skeleton = null; + else atlas = null; + } + } + + // 3) 解析 atlas 引用的贴图路径(多个同名贴图时,优先与 atlas 同文件夹/同批导入的) + let texturePaths = {}; + if (atlas) { + let text = ''; + try { text = fs.readFileSync(atlas.fullPath, 'utf8'); } catch (e) { /* ignore */ } + const pageNames = parseAtlasPages(text); + const atlasDir = path.dirname(atlas.fullPath); // atlas 所在 .info 目录 + for (const pn of pageNames) { + // 1) 优先使用 atlas 所在 .info 目录里的同名贴图(最可靠) + const inAtlasDir = path.join(atlasDir, pn); + if (fs.existsSync(inAtlasDir)) { + texturePaths[pn] = inAtlasDir; + continue; + } + // 2) 否则在候选里按“同 Eagle 文件夹 + 最近 btime”挑选 + let cands = textureFiles.filter((f) => f.name.toLowerCase() === pn.toLowerCase()); + if (cands.length === 0) cands = textureFiles.filter((f) => normalizeStem(f.name) === normalizeStem(pn)); + let hit = selectBest(cands, atlas.fullPath); + if (strictStem && hit && Math.abs(importTimeOf(hit.fullPath) - importTimeOf(atlas.fullPath)) > allowedImportDelta) hit = null; + if (hit) texturePaths[pn] = hit.fullPath; + } + } + + const base = skeleton ? normalizeStem(skeleton.name) : (atlas ? normalizeStem(atlas.name) : selectedStem); + const skelLower = skeleton ? skeleton.name.toLowerCase() : ''; + const skeletonIsBinary = skelLower.endsWith('.skel') || skelLower.endsWith('.skel.bytes'); + const chosenFamily = skeleton ? familyOfSkel(skeleton) : (atlas ? familyOfAtlas(atlas) : null); + const skeletonTime = skeleton ? importTimeOf(skeleton.fullPath) : 0; + const atlasTime = atlas ? importTimeOf(atlas.fullPath) : 0; + const relatedSkeletonPaths = skeleton ? realSkeletonFiles.filter((f) => + normalizeStem(f.name) === base && + familyOfSkel(f) === chosenFamily && + Math.abs(importTimeOf(f.fullPath) - skeletonTime) <= allowedImportDelta + ).map((f) => f.fullPath) : []; + const relatedAtlasPaths = atlas ? atlasFiles.filter((f) => + normalizeStem(f.name) === base && + familyOfAtlas(f) === chosenFamily && + Math.abs(importTimeOf(f.fullPath) - atlasTime) <= allowedImportDelta + ).map((f) => f.fullPath) : []; + const relatedDataPaths = [...new Set(relatedSkeletonPaths.concat(relatedAtlasPaths, [filePath]))] + .filter((fp) => isSkeletonFile(fp) || isAtlasFile(fp)); + + return { + skeletonPath: skeleton ? skeleton.fullPath : null, + atlasPath: atlas ? atlas.fullPath : null, + texturePaths, + base, + isBinary: skeletonIsBinary, + skeletonCandidates: realSkeletonFiles.map((f) => f.name), + skeletonCandidatePaths: realSkeletonFiles.map((f) => f.fullPath), + atlasCandidates: atlasFiles.map((f) => f.name), + atlasCandidatePaths: atlasFiles.map((f) => f.fullPath), + textureCandidates: textureFiles.map((f) => f.name), + relatedDataPaths, + }; +} + +/** 从 atlas 文本中解析出引用的贴图页面文件名 */ +function parseAtlasPages(atlasText) { + const pages = []; + if (!atlasText) return pages; + const lines = atlasText.split(/\r?\n/); + // atlas 中每个页面以一行“xxx.png”之类的文件名开始 + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (/\.(png|jpg|jpeg|webp)$/i.test(line)) { + pages.push(line); + } else if (line === '') { + // 空白行之后的下一个非空行可能是下一页文件名 + continue; + } + } + // 过滤掉显然是属性的行(例如 "size: 512,512"、"filter: " 等) + return pages.filter((p) => !/[=,:]/.test(p)); +} + +/** + * 读取 Atlas 页面声明的预乘设置。Spine 4.x 会为每个页面写入 + * `pma:true/false`;旧版 Atlas 通常没有该字段,此时返回 undefined。 + * Spine 的一次导出会让所有页面使用同一设置。若遇到手工拼接且声明冲突 + * 的 Atlas,采用第一个页面的声明,保持与页面/区域读取顺序一致。 + */ +function parseAtlasPma(atlasText) { + if (typeof atlasText !== 'string') return undefined; + const matches = Array.from(atlasText.matchAll(/^\s*pma\s*:\s*(true|false)\s*$/gim)); + return matches.length ? matches[0][1].toLowerCase() === 'true' : undefined; +} + +/** 找到应在首次预览时使用的皮肤:defaultSkin、名为 default 的皮肤、第一个皮肤。 */ +function preferredSkin(skeletonData) { + if (!skeletonData) return null; + if (skeletonData.defaultSkin) return skeletonData.defaultSkin; + const skins = skeletonData.skins || []; + return skins.find((skin) => skin && skin.name === 'default') || skins[0] || null; +} + +/** 应用皮肤并按 setup pose 重新解析槽位附件,跨 Spine 3.4–4.3 使用。 */ +function applySkin(skeleton, skin) { + if (!skeleton || !skin) return false; + if (typeof skeleton.setSkin === 'function') skeleton.setSkin(skin); + else if (typeof skeleton.setSkinByName === 'function') skeleton.setSkinByName(skin.name); + else return false; + if (typeof skeleton.setSlotsToSetupPose === 'function') skeleton.setSlotsToSetupPose(); + else if (typeof skeleton.setToSetupPose === 'function') skeleton.setToSetupPose(); + return true; +} + +module.exports = { + SKELETON_EXTS, + ATLAS_EXTS, + TEXTURE_EXTS, + ALL_EXTS, + extOf, + isSkeletonFile, + isAtlasFile, + isTextureFile, + stemOf, + normalizeStem, + detectVersion, + detectVersionFromJson, + detectVersionFromBuffer, + chooseRuntimeDir, + classifySkeletonJson, + looksLikeSkeletonJson, + discoverAssets, + parseAtlasPages, + parseAtlasPma, + preferredSkin, + applySkin, + isEagleItemDir, + getSearchRoots, + collectSpineFiles, + foldersOfItem, + findLibraryRoot, + readFolderInfo, + getValidFolders, + mtimeOf, + btimeOf, + importTimeOf, + versionFamily, + atlasFamily, + itemMeta, + isItemDeleted, +}; diff --git a/release/MAC版本/js/spine-webgl-rasterizer.js b/release/MAC版本/js/spine-webgl-rasterizer.js new file mode 100644 index 0000000..8aa147d --- /dev/null +++ b/release/MAC版本/js/spine-webgl-rasterizer.js @@ -0,0 +1,177 @@ +'use strict'; + +// Decode file bytes without the Canvas 2D premultiply/unpremultiply round trip. +// In low-alpha PMA pixels that round trip destroys RGB precision before blending. +const preparedTextures = new WeakMap(); +async function prepareTexture(image, blob) { + if (typeof createImageBitmap !== 'function') return; + const options = { colorSpaceConversion: 'none' }; + const [pma, straight] = await Promise.all([ + createImageBitmap(blob, { ...options, premultiplyAlpha: 'none' }), + createImageBitmap(blob, { ...options, premultiplyAlpha: 'premultiply' }) + ]); + preparedTextures.set(image, { pma, straight }); +} + +// Rasterize adjacent mesh triangles together, with GPU edge ownership rules. +// Canvas clip()+drawImage() anti-aliases each triangle separately and exposes +// the background along shared edges, which looks like a wireframe overlay. +function createRasterizer(context) { + const document = context.canvas && context.canvas.ownerDocument; + if (!document || typeof context.getTransform !== 'function') return null; + const canvas = document.createElement('canvas'); + const gl = canvas.getContext('webgl', { + alpha: true, premultipliedAlpha: true, antialias: true, + preserveDrawingBuffer: true, depth: false, stencil: false + }); + if (!gl) return null; + function shader(type, source) { + const shader = gl.createShader(type); + gl.shaderSource(shader, source); gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(shader)); + return shader; + } + const vertex = shader(gl.VERTEX_SHADER, ` + attribute vec2 position; + attribute vec2 uv; + attribute vec4 light; + attribute vec4 dark; + uniform vec2 resolution; + varying vec2 textureUV; + varying vec4 lightColor; + varying vec4 darkColor; + void main() { + vec2 p = position / resolution * 2.0 - 1.0; + gl_Position = vec4(p.x, -p.y, 0.0, 1.0); + textureUV = uv; + lightColor = light; darkColor = dark; + }`); + const fragment = shader(gl.FRAGMENT_SHADER, ` + precision mediump float; + uniform sampler2D image; + varying vec2 textureUV; + varying vec4 lightColor; + varying vec4 darkColor; + void main() { + vec4 color = texture2D(image, textureUV); + float alpha = color.a * lightColor.a; + // Textures are PMA in GPU memory. Light/dark colors arrive straight. + vec3 rgb = (color.rgb * lightColor.rgb + (color.a - color.rgb) * darkColor.rgb) * lightColor.a; + gl_FragColor = vec4(rgb, alpha); + }`); + const program = gl.createProgram(); gl.attachShader(program, vertex); gl.attachShader(program, fragment); gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(program)); + gl.deleteShader(vertex); gl.deleteShader(fragment); + const buffer = gl.createBuffer(); + const position = gl.getAttribLocation(program, 'position'), uv = gl.getAttribLocation(program, 'uv'); + const resolution = gl.getUniformLocation(program, 'resolution'); + const light = gl.getAttribLocation(program, 'light'), dark = gl.getAttribLocation(program, 'dark'); + const textures = new Map(); + let coordinates = [], currentImage = null, currentAlpha = 1, currentMode = 'source-over', transform; + let disposed = false, lost = false; + let premultipliedAlpha = false; + canvas.addEventListener('webglcontextlost', event => { event.preventDefault(); lost = true; }); + function texture(image) { + const pma = image !== context.canvas && premultipliedAlpha; + let pair = textures.get(image); + if (!pair) { pair = {}; textures.set(image, pair); } + const key = pma ? 'pma' : 'straight'; + if (pair[key] && image !== context.canvas) return pair[key]; + const t = pair[key] || gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, t); + // Premultiply before interpolation so translucent edges do not darken. + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !pma); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + const prepared = preparedTextures.get(image); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prepared ? prepared[key] : image); + pair[key] = t; return t; + } + function flush() { + if (!coordinates.length) return; + gl.bindTexture(gl.TEXTURE_2D, texture(currentImage)); + // Premultiplied RGB factors; keep source-over alpha independently. + const factors = currentMode === 'lighter' ? [gl.ONE, gl.ONE] + : currentMode === 'multiply' ? [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA] + : currentMode === 'screen' ? [gl.ONE, gl.ONE_MINUS_SRC_COLOR] + : [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + gl.blendFuncSeparate(factors[0], factors[1], gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coordinates), gl.STREAM_DRAW); + gl.drawArrays(gl.TRIANGLES, 0, coordinates.length / 12); + coordinates.length = 0; + } + return { + begin(pma = false) { + if (disposed || lost || gl.isContextLost()) return false; + premultipliedAlpha = pma; + const target = context.canvas; + if (canvas.width !== target.width) canvas.width = target.width; + if (canvas.height !== target.height) canvas.height = target.height; + transform = context.getTransform(); coordinates.length = 0; currentImage = null; + gl.viewport(0, 0, canvas.width, canvas.height); + gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); + gl.useProgram(program); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.enableVertexAttribArray(position); gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 48, 0); + gl.enableVertexAttribArray(uv); gl.vertexAttribPointer(uv, 2, gl.FLOAT, false, 48, 8); + gl.enableVertexAttribArray(light); gl.vertexAttribPointer(light, 4, gl.FLOAT, false, 48, 16); + gl.enableVertexAttribArray(dark); gl.vertexAttribPointer(dark, 4, gl.FLOAT, false, 48, 32); + gl.uniform2f(resolution, canvas.width, canvas.height); + gl.activeTexture(gl.TEXTURE0); gl.uniform1i(gl.getUniformLocation(program, 'image'), 0); + gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + // Seed the same framebuffer with the actual Canvas pixels (solid or + // checkerboard background). CSS backgrounds cannot participate in blending. + currentImage = target; currentAlpha = 1; currentMode = 'source-over'; + const w = canvas.width, h = canvas.height; + for (const vertex of [[0,0,0,0],[w,0,1,0],[w,h,1,1],[0,0,0,0],[w,h,1,1],[0,h,0,1]]) + coordinates.push(...vertex, 1,1,1,1, 0,0,0,0); + flush(); currentImage = null; + return true; + }, + triangle(image, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2, colors, darkColors) { + const alpha = context.globalAlpha; + const mode = context.globalCompositeOperation || 'source-over'; + if (image !== currentImage || alpha !== currentAlpha || mode !== currentMode) { flush(); currentImage = image; currentAlpha = alpha; currentMode = mode; } + const t = transform; + const points = [[x0,y0,u0,v0],[x1,y1,u1,v1],[x2,y2,u2,v2]]; + for (let i=0; i<3; i++) { + const [x,y,u,v] = points[i], j=i*4; + coordinates.push(t.a*x+t.c*y+t.e, t.b*x+t.d*y+t.f, u,v, + ...(colors ? colors.slice(j,j+4) : [1,1,1,alpha]), + ...(darkColors ? darkColors.slice(j,j+4) : [0,0,0,0])); + } + }, + end() { + flush(); + context.save(); + try { context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; context.globalCompositeOperation = 'copy'; context.drawImage(canvas, 0, 0); } + finally { context.restore(); } + }, + dispose() { + if (disposed) return; disposed = true; + for (const pair of textures.values()) for (const value of Object.values(pair)) gl.deleteTexture(value); + textures.clear(); gl.deleteBuffer(buffer); gl.deleteProgram(program); + const extension = gl.getExtension('WEBGL_lose_context'); if (extension) extension.loseContext(); + } + }; +} + +function attach(renderer, context) { + let rasterizer; + try { rasterizer = createRasterizer(context); } catch (e) { return renderer; } + if (!rasterizer) return renderer; + const draw = renderer.draw.bind(renderer), triangle = renderer.drawTriangle.bind(renderer); + renderer.draw = skeleton => { + if (!rasterizer.begin(!!renderer.premultipliedAlpha)) return draw(skeleton); + renderer.gpuDrawing = true; + renderer.drawTriangle = rasterizer.triangle; + try { draw(skeleton); rasterizer.end(); } + finally { renderer.drawTriangle = triangle; renderer.gpuDrawing = false; } + }; + renderer.dispose = rasterizer.dispose; + renderer.rasterization = 'webgl'; + return renderer; +} + +module.exports = { createRasterizer, attach, prepareTexture }; diff --git a/release/MAC版本/lib/3.4/README.md b/release/MAC版本/lib/3.4/README.md new file mode 100644 index 0000000..a2b7131 --- /dev/null +++ b/release/MAC版本/lib/3.4/README.md @@ -0,0 +1,9 @@ +# Spine 3.4 runtime + +Bundled from the official `3.4.02` tag, commit `ef5013143178918ddfc7cabfbddeae7aec7cf84e`, `spine-ts/build/spine-canvas.js`. + +Local correction: `SkeletonJson` path-length loop writes `lengths[i]`, not `lengths[i++]`. The original increments twice and reads beyond the source array, producing missing/NaN lengths. + +The plugin provides binary decoding and the `AtlasAttachmentLoader` name alias in `js/spine-legacy-binary.js`. Rendering uses the 3.4 attachment vertex API in `js/spine-canvas-clipping.js`. 3.4 has no clipping attachments; no newer attachment types are synthesized. + +License: `LICENSES/Spine-3.4-License.txt`. diff --git a/release/MAC版本/lib/3.4/spine-canvas.js b/release/MAC版本/lib/3.4/spine-canvas.js new file mode 100644 index 0000000..7ea5529 --- /dev/null +++ b/release/MAC版本/lib/3.4/spine-canvas.js @@ -0,0 +1,4767 @@ +var spine; +(function (spine) { + var AssetManager = (function () { + function AssetManager(textureLoader, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + } + AssetManager.prototype.loadText = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + if (success) + success(path, request.responseText); + _this.assets[path] = request.responseText; + } + else { + if (error) + error(path, "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText); + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + _this.toLoad--; + _this.loaded++; + } + }; + request.open("GET", path, true); + request.send(); + }; + AssetManager.prototype.loadTexture = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.src = path; + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + if (success) + success(path, img); + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + }; + img.onerror = function (ev) { + if (error) + error(path, "Couldn't load image " + path); + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + }; + }; + AssetManager.prototype.get = function (path) { + path = this.pathPrefix + path; + return this.assets[path]; + }; + AssetManager.prototype.remove = function (path) { + path = this.pathPrefix + path; + var asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + this.assets[path] = null; + }; + AssetManager.prototype.removeAll = function () { + for (var key in this.assets) { + var asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + }; + AssetManager.prototype.isLoadingComplete = function () { + return this.toLoad == 0; + }; + AssetManager.prototype.getToLoad = function () { + return this.toLoad; + }; + AssetManager.prototype.getLoaded = function () { + return this.loaded; + }; + AssetManager.prototype.dispose = function () { + this.removeAll(); + }; + AssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + AssetManager.prototype.getErrors = function () { + return this.errors; + }; + return AssetManager; + }()); + spine.AssetManager = AssetManager; +})(spine || (spine = {})); +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + _super.call(this, function (image) { return new spine.canvas.CanvasTexture(image); }, pathPrefix); + } + return AssetManager; + }(spine.AssetManager)); + canvas.AssetManager = AssetManager; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(spine.TextureFilter || (spine.TextureFilter = {})); + var TextureFilter = spine.TextureFilter; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(spine.TextureWrap || (spine.TextureWrap = {})); + var TextureWrap = spine.TextureWrap; + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var CanvasTexture = (function (_super) { + __extends(CanvasTexture, _super); + function CanvasTexture(image) { + _super.call(this, image); + } + CanvasTexture.prototype.setFilters = function (minFilter, magFilter) { }; + CanvasTexture.prototype.setWraps = function (uWrap, vWrap) { }; + CanvasTexture.prototype.dispose = function () { }; + return CanvasTexture; + }(spine.Texture)); + canvas.CanvasTexture = CanvasTexture; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var SkeletonRenderer = (function () { + function SkeletonRenderer(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.ctx = context; + } + SkeletonRenderer.prototype.draw = function (skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + }; + SkeletonRenderer.prototype.drawImages = function (skeleton) { + var ctx = this.ctx; + var drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var region = null; + var image = null; + var vertices = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = regionAttachment.updateWorldVertices(slot, false); + region = regionAttachment.region; + image = (region).texture.getImage(); + } + else + continue; + var att = attachment; + var bone = slot.bone; + var x = vertices[0]; + var y = vertices[1]; + var rotation = (bone.getWorldRotationX() - att.rotation) * Math.PI / 180; + var xx = vertices[24] - vertices[0]; + var xy = vertices[25] - vertices[1]; + var yx = vertices[8] - vertices[0]; + var yy = vertices[9] - vertices[1]; + var w = Math.sqrt(xx * xx + xy * xy), h = -Math.sqrt(yx * yx + yy * yy); + ctx.translate(x, y); + ctx.rotate(rotation); + if (region.rotate) { + ctx.rotate(Math.PI / 2); + ctx.drawImage(image, region.x, region.y, region.height, region.width, 0, 0, h, -w); + ctx.rotate(-Math.PI / 2); + } + else { + ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h); + } + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.rotate(-rotation); + ctx.translate(-x, -y); + } + }; + SkeletonRenderer.prototype.drawTriangles = function (skeleton) { + var blendMode = null; + var vertices = null; + var triangles = null; + var drawOrder = skeleton.drawOrder; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var texture = null; + var region = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = regionAttachment.updateWorldVertices(slot, false); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.texture.getImage(); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + vertices = mesh.updateWorldVertices(slot, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture.getImage(); + } + else + continue; + if (texture != null) { + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + } + var ctx = this.ctx; + for (var j = 0; j < triangles.length; j += 3) { + var t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + var x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + var x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + var 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + }; + SkeletonRenderer.prototype.drawTriangle = function (img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + var ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + return SkeletonRenderer; + }()); + canvas.SkeletonRenderer = SkeletonRenderer; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Animation = (function () { + function Animation(name, timelines, duration) { + if (name == null) + throw new Error("name cannot be null."); + if (timelines == null) + throw new Error("timelines cannot be null."); + this.name = name; + this.timelines = timelines; + this.duration = duration; + } + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, 1); + }; + Animation.prototype.mix = function (skeleton, lastTime, time, loop, events, alpha) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha); + }; + Animation.binarySearch = function (values, target, step) { + if (step === void 0) { step = 1; } + var low = 0; + var high = values.length / step - 2; + if (high == 0) + return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) + return (low + 1) * step; + current = (low + high) >>> 1; + } + }; + Animation.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) + return i; + return -1; + }; + return Animation; + }()); + spine.Animation = Animation; + var CurveTimeline = (function () { + function CurveTimeline(frameCount) { + if (frameCount <= 0) + throw new Error("frameCount must be > 0: " + frameCount); + this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE); + } + CurveTimeline.prototype.getFrameCount = function () { + return this.curves.length / CurveTimeline.BEZIER_SIZE + 1; + }; + CurveTimeline.prototype.setLinear = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR; + }; + CurveTimeline.prototype.setStepped = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED; + }; + CurveTimeline.prototype.getCurveType = function (frameIndex) { + var index = frameIndex * CurveTimeline.BEZIER_SIZE; + if (index == this.curves.length) + return CurveTimeline.LINEAR; + var type = this.curves[index]; + if (type == CurveTimeline.LINEAR) + return CurveTimeline.LINEAR; + if (type == CurveTimeline.STEPPED) + return CurveTimeline.STEPPED; + return CurveTimeline.BEZIER; + }; + CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) { + var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03; + var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; + var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var curves = this.curves; + curves[i++] = CurveTimeline.BEZIER; + var x = dfx, y = dfy; + for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + }; + CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) { + percent = spine.MathUtils.clamp(percent, 0, 1); + var curves = this.curves; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var type = curves[i]; + if (type == CurveTimeline.LINEAR) + return percent; + if (type == CurveTimeline.STEPPED) + return 0; + i++; + var x = 0; + for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + x = curves[i]; + if (x >= percent) { + var prevX = void 0, prevY = void 0; + if (i == start) { + prevX = 0; + prevY = 0; + } + else { + prevX = curves[i - 2]; + prevY = curves[i - 1]; + } + return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + var y = curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); + }; + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; + return CurveTimeline; + }()); + spine.CurveTimeline = CurveTimeline; + var RotateTimeline = (function (_super) { + __extends(RotateTimeline, _super); + function RotateTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount << 1); + } + RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) { + frameIndex <<= 1; + this.frames[frameIndex] = time; + this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; + }; + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var bone = skeleton.bones[this.boneIndex]; + if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { + var amount_1 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; + while (amount_1 > 180) + amount_1 -= 360; + while (amount_1 < -180) + amount_1 += 360; + bone.rotation += amount_1 * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES); + var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); + var amount = frames[frame + RotateTimeline.ROTATION] - prevRotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + amount = bone.data.rotation + (prevRotation + amount * percent) - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + }; + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; + return RotateTimeline; + }(CurveTimeline)); + spine.RotateTimeline = RotateTimeline; + var TranslateTimeline = (function (_super) { + __extends(TranslateTimeline, _super); + function TranslateTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + } + TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) { + frameIndex *= TranslateTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TranslateTimeline.X] = x; + this.frames[frameIndex + TranslateTimeline.Y] = y; + }; + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var bone = skeleton.bones[this.boneIndex]; + if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) { + bone.x += (bone.data.x + frames[frames.length + TranslateTimeline.PREV_X] - bone.x) * alpha; + bone.y += (bone.data.y + frames[frames.length + TranslateTimeline.PREV_Y] - bone.y) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES); + var prevX = frames[frame + TranslateTimeline.PREV_X]; + var prevY = frames[frame + TranslateTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime)); + bone.x += (bone.data.x + prevX + (frames[frame + TranslateTimeline.X] - prevX) * percent - bone.x) * alpha; + bone.y += (bone.data.y + prevY + (frames[frame + TranslateTimeline.Y] - prevY) * percent - bone.y) * alpha; + }; + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; + return TranslateTimeline; + }(CurveTimeline)); + spine.TranslateTimeline = TranslateTimeline; + var ScaleTimeline = (function (_super) { + __extends(ScaleTimeline, _super); + function ScaleTimeline(frameCount) { + _super.call(this, frameCount); + } + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var bone = skeleton.bones[this.boneIndex]; + if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) { + bone.scaleX += (bone.data.scaleX * frames[frames.length + ScaleTimeline.PREV_X] - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY * frames[frames.length + ScaleTimeline.PREV_Y] - bone.scaleY) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES); + var prevX = frames[frame + ScaleTimeline.PREV_X]; + var prevY = frames[frame + ScaleTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime)); + bone.scaleX += (bone.data.scaleX * (prevX + (frames[frame + ScaleTimeline.X] - prevX) * percent) - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY * (prevY + (frames[frame + ScaleTimeline.Y] - prevY) * percent) - bone.scaleY) * alpha; + }; + return ScaleTimeline; + }(TranslateTimeline)); + spine.ScaleTimeline = ScaleTimeline; + var ShearTimeline = (function (_super) { + __extends(ShearTimeline, _super); + function ShearTimeline(frameCount) { + _super.call(this, frameCount); + } + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var bone = skeleton.bones[this.boneIndex]; + if (time >= frames[frames.length - ShearTimeline.ENTRIES]) { + bone.shearX += (bone.data.shearX + frames[frames.length + ShearTimeline.PREV_X] - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + frames[frames.length + ShearTimeline.PREV_Y] - bone.shearY) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES); + var prevX = frames[frame + ShearTimeline.PREV_X]; + var prevY = frames[frame + ShearTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime)); + bone.shearX += (bone.data.shearX + (prevX + (frames[frame + ShearTimeline.X] - prevX) * percent) - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + (prevY + (frames[frame + ShearTimeline.Y] - prevY) * percent) - bone.shearY) * alpha; + }; + return ShearTimeline; + }(TranslateTimeline)); + spine.ShearTimeline = ShearTimeline; + var ColorTimeline = (function (_super) { + __extends(ColorTimeline, _super); + function ColorTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + } + ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) { + frameIndex *= ColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + ColorTimeline.R] = r; + this.frames[frameIndex + ColorTimeline.G] = g; + this.frames[frameIndex + ColorTimeline.B] = b; + this.frames[frameIndex + ColorTimeline.A] = a; + }; + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var r = 0, g = 0, b = 0, a = 0; + if (time >= frames[frames.length - ColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + ColorTimeline.PREV_R]; + g = frames[i + ColorTimeline.PREV_G]; + b = frames[i + ColorTimeline.PREV_B]; + a = frames[i + ColorTimeline.PREV_A]; + } + else { + var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES); + r = frames[frame + ColorTimeline.PREV_R]; + g = frames[frame + ColorTimeline.PREV_G]; + b = frames[frame + ColorTimeline.PREV_B]; + a = frames[frame + ColorTimeline.PREV_A]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + ColorTimeline.R] - r) * percent; + g += (frames[frame + ColorTimeline.G] - g) * percent; + b += (frames[frame + ColorTimeline.B] - b) * percent; + a += (frames[frame + ColorTimeline.A] - a) * percent; + } + var color = skeleton.slots[this.slotIndex].color; + if (alpha < 1) + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + else + color.set(r, g, b, a); + }; + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; + return ColorTimeline; + }(CurveTimeline)); + spine.ColorTimeline = ColorTimeline; + var AttachmentTimeline = (function () { + function AttachmentTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.attachmentNames = new Array(frameCount); + } + AttachmentTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }; + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var frameIndex = 0; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = Animation.binarySearch(frames, time, 1) - 1; + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex] + .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + return AttachmentTimeline; + }()); + spine.AttachmentTimeline = AttachmentTimeline; + var EventTimeline = (function () { + function EventTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.events = new Array(frameCount); + } + EventTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + EventTimeline.prototype.setFrame = function (frameIndex, event) { + this.frames[frameIndex] = event.time; + this.events[frameIndex] = event; + }; + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + if (firedEvents == null) + return; + var frames = this.frames; + var frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha); + lastTime = -1; + } + else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + var frame = 0; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.binarySearch(frames, lastTime); + var frameTime = frames[frame]; + while (frame > 0) { + if (frames[frame - 1] != frameTime) + break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.push(this.events[frame]); + }; + return EventTimeline; + }()); + spine.EventTimeline = EventTimeline; + var DrawOrderTimeline = (function () { + function DrawOrderTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.drawOrders = new Array(frameCount); + } + DrawOrderTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) { + this.frames[frameIndex] = time; + this.drawOrders[frameIndex] = drawOrder; + }; + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var frame = 0; + if (time >= frames[frames.length - 1]) + frame = frames.length - 1; + else + frame = Animation.binarySearch(frames, time) - 1; + var drawOrder = skeleton.drawOrder; + var slots = skeleton.slots; + var drawOrderToSetupIndex = this.drawOrders[frame]; + if (drawOrderToSetupIndex == null) + spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length); + else { + for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + }; + return DrawOrderTimeline; + }()); + spine.DrawOrderTimeline = DrawOrderTimeline; + var DeformTimeline = (function (_super) { + __extends(DeformTimeline, _super); + function DeformTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount); + this.frameVertices = new Array(frameCount); + } + DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { + this.frames[frameIndex] = time; + this.frameVertices[frameIndex] = vertices; + }; + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var slot = skeleton.slots[this.slotIndex]; + var slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) + return; + var frames = this.frames; + if (time < frames[0]) + return; + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + var verticesArray = slot.attachmentVertices; + if (verticesArray.length != vertexCount) + alpha = 1; + var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); + if (time >= frames[frames.length - 1]) { + var lastVertices = frameVertices[frames.length - 1]; + if (alpha < 1) { + for (var i = 0; i < vertexCount; i++) + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + } + else + spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); + return; + } + var frame = Animation.binarySearch(frames, time); + var prevVertices = frameVertices[frame - 1]; + var nextVertices = frameVertices[frame]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + if (alpha < 1) { + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + } + else { + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i]; + vertices[i] = prev + (nextVertices[i] - prev) * percent; + } + } + }; + return DeformTimeline; + }(CurveTimeline)); + spine.DeformTimeline = DeformTimeline; + var IkConstraintTimeline = (function (_super) { + __extends(IkConstraintTimeline, _super); + function IkConstraintTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + } + IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection) { + frameIndex *= IkConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; + this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; + }; + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { + constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; + constraint.bendDirection = Math.floor(frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]); + return; + } + var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES); + var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); + constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; + constraint.bendDirection = Math.floor(frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]); + }; + IkConstraintTimeline.ENTRIES = 3; + IkConstraintTimeline.PREV_TIME = -3; + IkConstraintTimeline.PREV_MIX = -2; + IkConstraintTimeline.PREV_BEND_DIRECTION = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.BEND_DIRECTION = 2; + return IkConstraintTimeline; + }(CurveTimeline)); + spine.IkConstraintTimeline = IkConstraintTimeline; + var TransformConstraintTimeline = (function (_super) { + __extends(TransformConstraintTimeline, _super); + function TransformConstraintTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + } + TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) { + frameIndex *= TransformConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix; + this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; + this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; + }; + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) { + var i = frames.length; + constraint.rotateMix += (frames[i + TransformConstraintTimeline.PREV_ROTATE] - constraint.rotateMix) * alpha; + constraint.translateMix += (frames[i + TransformConstraintTimeline.PREV_TRANSLATE] - constraint.translateMix) * alpha; + constraint.scaleMix += (frames[i + TransformConstraintTimeline.PREV_SCALE] - constraint.scaleMix) * alpha; + constraint.shearMix += (frames[i + TransformConstraintTimeline.PREV_SHEAR] - constraint.shearMix) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES); + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime)); + var rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE]; + var translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE]; + var scale = frames[frame + TransformConstraintTimeline.PREV_SCALE]; + var shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR]; + constraint.rotateMix += (rotate + (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent - constraint.rotateMix) * alpha; + constraint.translateMix += (translate + (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent - constraint.translateMix) + * alpha; + constraint.scaleMix += (scale + (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent - constraint.scaleMix) * alpha; + constraint.shearMix += (shear + (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent - constraint.shearMix) * alpha; + }; + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; + return TransformConstraintTimeline; + }(CurveTimeline)); + spine.TransformConstraintTimeline = TransformConstraintTimeline; + var PathConstraintPositionTimeline = (function (_super) { + __extends(PathConstraintPositionTimeline, _super); + function PathConstraintPositionTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + } + PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) { + frameIndex *= PathConstraintPositionTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; + }; + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES]) { + var i = frames.length; + constraint.position += (frames[i + PathConstraintPositionTimeline.PREV_VALUE] - constraint.position) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES); + var position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); + constraint.position += (position + (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent - constraint.position) * alpha; + }; + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; + return PathConstraintPositionTimeline; + }(CurveTimeline)); + spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; + var PathConstraintSpacingTimeline = (function (_super) { + __extends(PathConstraintSpacingTimeline, _super); + function PathConstraintSpacingTimeline(frameCount) { + _super.call(this, frameCount); + } + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES]) { + var i = frames.length; + constraint.spacing += (frames[i + PathConstraintSpacingTimeline.PREV_VALUE] - constraint.spacing) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES); + var spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); + constraint.spacing += (spacing + (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent - constraint.spacing) * alpha; + }; + return PathConstraintSpacingTimeline; + }(PathConstraintPositionTimeline)); + spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline; + var PathConstraintMixTimeline = (function (_super) { + __extends(PathConstraintMixTimeline, _super); + function PathConstraintMixTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + } + PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) { + frameIndex *= PathConstraintMixTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; + }; + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha) { + var frames = this.frames; + if (time < frames[0]) + return; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) { + var i = frames.length; + constraint.rotateMix += (frames[i + PathConstraintMixTimeline.PREV_ROTATE] - constraint.rotateMix) * alpha; + constraint.translateMix += (frames[i + PathConstraintMixTimeline.PREV_TRANSLATE] - constraint.translateMix) * alpha; + return; + } + var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES); + var rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE]; + var translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime)); + constraint.rotateMix += (rotate + (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent - constraint.rotateMix) * alpha; + constraint.translateMix += (translate + (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent - constraint.translateMix) + * alpha; + }; + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; + return PathConstraintMixTimeline; + }(CurveTimeline)); + spine.PathConstraintMixTimeline = PathConstraintMixTimeline; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationState = (function () { + function AnimationState(data) { + if (data === void 0) { data = null; } + this.tracks = new Array(); + this.events = new Array(); + this.listeners = new Array(); + this.timeScale = 1; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + } + AnimationState.prototype.update = function (delta) { + delta *= this.timeScale; + for (var i = 0; i < this.tracks.length; i++) { + var current = this.tracks[i]; + if (current == null) + continue; + var next = current.next; + if (next != null) { + var nextTime = current.lastTime - next.delay; + if (nextTime >= 0) { + var nextDelta = delta * next.timeScale; + next.time = nextTime + nextDelta; + current.time += delta * current.timeScale; + this.setCurrent(i, next); + next.time -= nextDelta; + current = next; + } + } + else if (!current.loop && current.lastTime >= current.endTime) { + this.clearTrack(i); + continue; + } + current.time += delta * current.timeScale; + if (current.previous != null) { + var previousDelta = delta * current.previous.timeScale; + current.previous.time += previousDelta; + current.mixTime += previousDelta; + } + } + }; + AnimationState.prototype.apply = function (skeleton) { + var events = this.events; + var listenerCount = this.listeners.length; + for (var i = 0; i < this.tracks.length; i++) { + var current = this.tracks[i]; + if (current == null) + continue; + events.length = 0; + var time = current.time; + var lastTime = current.lastTime; + var endTime = current.endTime; + var loop = current.loop; + if (!loop && time > endTime) + time = endTime; + var previous = current.previous; + if (previous == null) + current.animation.mix(skeleton, lastTime, time, loop, events, current.mix); + else { + var previousTime = previous.time; + if (!previous.loop && previousTime > previous.endTime) + previousTime = previous.endTime; + previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null); + var alpha = current.mixTime / current.mixDuration * current.mix; + if (alpha >= 1) { + alpha = 1; + current.previous = null; + } + current.animation.mix(skeleton, lastTime, time, loop, events, alpha); + } + for (var ii = 0, nn = events.length; ii < nn; ii++) { + var event_1 = events[ii]; + if (current.listener != null && current.listener.event != null) + current.listener.event(i, event_1); + for (var iii = 0; iii < listenerCount; iii++) + if (this.listeners[iii].event) + this.listeners[iii].event(i, event_1); + } + if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) { + var count = spine.MathUtils.toInt(time / endTime); + if (current.listener != null && current.listener.complete) + current.listener.complete(i, count); + for (var ii = 0, nn = this.listeners.length; ii < nn; ii++) + if (this.listeners[ii].complete) + this.listeners[ii].complete(i, count); + } + current.lastTime = current.time; + } + }; + AnimationState.prototype.clearTracks = function () { + for (var i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + }; + AnimationState.prototype.clearTrack = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return; + var current = this.tracks[trackIndex]; + if (current == null) + return; + if (current.listener != null && current.listener.end != null) + current.listener.end(trackIndex); + for (var i = 0, n = this.listeners.length; i < n; i++) + if (this.listeners[i].end) + this.listeners[i].end(trackIndex); + this.tracks[trackIndex] = null; + this.freeAll(current); + }; + AnimationState.prototype.freeAll = function (entry) { + while (entry != null) { + var next = entry.next; + entry = next; + } + }; + AnimationState.prototype.expandToIndex = function (index) { + if (index < this.tracks.length) + return this.tracks[index]; + spine.Utils.setArraySize(this.tracks, index - this.tracks.length + 1, null); + this.tracks.length = index + 1; + return null; + }; + AnimationState.prototype.setCurrent = function (index, entry) { + var current = this.expandToIndex(index); + if (current != null) { + var previous = current.previous; + current.previous = null; + if (current.listener != null && current.listener.end != null) + current.listener.end(index); + for (var i = 0, n = this.listeners.length; i < n; i++) + if (this.listeners[i].end) + this.listeners[i].end(index); + entry.mixDuration = this.data.getMix(current.animation, entry.animation); + if (entry.mixDuration > 0) { + entry.mixTime = 0; + if (previous != null && current.mixTime / current.mixDuration < 0.5) { + entry.previous = previous; + previous = current; + } + else + entry.previous = current; + } + } + this.tracks[index] = entry; + if (entry.listener != null && entry.listener.start != null) + entry.listener.start(index); + for (var i = 0, n = this.listeners.length; i < n; i++) + if (this.listeners[i].start) + this.listeners[i].start(index); + }; + AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + }; + AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) { + var current = this.expandToIndex(trackIndex); + if (current != null) + this.freeAll(current.next); + var entry = new TrackEntry(); + entry.animation = animation; + entry.loop = loop; + entry.endTime = animation.duration; + this.setCurrent(trackIndex, entry); + return entry; + }; + AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + }; + AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) { + var entry = new TrackEntry(); + entry.animation = animation; + entry.loop = loop; + entry.endTime = animation.duration; + var last = this.expandToIndex(trackIndex); + if (last != null) { + while (last.next != null) + last = last.next; + last.next = entry; + } + else + this.tracks[trackIndex] = entry; + if (delay <= 0) { + if (last != null) + delay += last.endTime - this.data.getMix(last.animation, animation); + else + delay = 0; + } + entry.delay = delay; + return entry; + }; + AnimationState.prototype.getCurrent = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + }; + AnimationState.prototype.addListener = function (listener) { + if (listener == null) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + }; + AnimationState.prototype.removeListener = function (listener) { + var index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + }; + AnimationState.prototype.clearListeners = function () { + this.listeners.length = 0; + }; + return AnimationState; + }()); + spine.AnimationState = AnimationState; + var TrackEntry = (function () { + function TrackEntry() { + this.loop = false; + this.delay = 0; + this.time = 0; + this.lastTime = -1; + this.endTime = 0; + this.timeScale = 1; + this.mixTime = 0; + this.mixDuration = 0; + this.mix = 1; + } + TrackEntry.prototype.reset = function () { + this.next = null; + this.previous = null; + this.animation = null; + this.listener = null; + this.timeScale = 1; + this.lastTime = -1; + this.time = 0; + }; + TrackEntry.prototype.isComplete = function () { + return this.time >= this.endTime; + }; + return TrackEntry; + }()); + spine.TrackEntry = TrackEntry; + var AnimationStateAdapter = (function () { + function AnimationStateAdapter() { + } + AnimationStateAdapter.prototype.event = function (trackIndex, event) { + }; + AnimationStateAdapter.prototype.complete = function (trackIndex, loopCount) { + }; + AnimationStateAdapter.prototype.start = function (trackIndex) { + }; + AnimationStateAdapter.prototype.end = function (trackIndex) { + }; + return AnimationStateAdapter; + }()); + spine.AnimationStateAdapter = AnimationStateAdapter; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationStateData = (function () { + function AnimationStateData(skeletonData) { + this.animationToMixTime = {}; + this.defaultMix = 0; + if (skeletonData == null) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + AnimationStateData.prototype.setMix = function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (from == null) + throw new Error("Animation not found: " + fromName); + var to = this.skeletonData.findAnimation(toName); + if (to == null) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + }; + AnimationStateData.prototype.setMixWith = function (from, to, duration) { + if (from == null) + throw new Error("from cannot be null."); + if (to == null) + throw new Error("to cannot be null."); + var key = from.name + to.name; + this.animationToMixTime[key] = duration; + }; + AnimationStateData.prototype.getMix = function (from, to) { + var key = from.name + to.name; + var value = this.animationToMixTime[key]; + return value === undefined ? this.defaultMix : value; + }; + return AnimationStateData; + }()); + spine.AnimationStateData = AnimationStateData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + _super.call(this, name); + this.worldVerticesLength = 0; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, worldVertices) { + this.computeWorldVerticesWith(slot, 0, this.worldVerticesLength, worldVertices, 0); + }; + VertexAttachment.prototype.computeWorldVerticesWith = function (slot, start, count, worldVertices, offset) { + count += offset; + var skeleton = slot.bone.skeleton; + var x = skeleton.x, y = skeleton.y; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + x += bone.worldX; + y += bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += 2) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += 2) { + var wx = x, wy = y; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { + var wx = x, wy = y; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; + }; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + })(spine.AttachmentType || (spine.AttachmentType = {})); + var AttachmentType = spine.AttachmentType; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + _super.call(this, name); + this.color = new spine.Color(1, 1, 1, 1); + } + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + _super.call(this, name); + this.color = new spine.Color(1, 1, 1, 1); + this.inheritDeform = false; + this.tempColor = new spine.Color(0, 0, 0, 0); + } + MeshAttachment.prototype.updateUVs = function () { + var regionUVs = this.regionUVs; + var verticesLength = regionUVs.length; + var worldVerticesLength = (verticesLength >> 1) * 8; + if (this.worldVertices == null || this.worldVertices.length != worldVerticesLength) + this.worldVertices = spine.Utils.newFloatArray(worldVerticesLength); + var u = 0, v = 0, width = 0, height = 0; + if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; + } + if (this.region.rotate) { + for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { + this.worldVertices[w] = u + regionUVs[i + 1] * width; + this.worldVertices[w + 1] = v + height - regionUVs[i] * height; + } + } + else { + for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { + this.worldVertices[w] = u + regionUVs[i] * width; + this.worldVertices[w + 1] = v + regionUVs[i + 1] * height; + } + } + }; + MeshAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = this.color; + var alpha = skeletonColor.a * slotColor.a * meshColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier, skeletonColor.g * slotColor.g * meshColor.g * multiplier, skeletonColor.b * slotColor.b * meshColor.b * multiplier, alpha); + var x = skeleton.x, y = skeleton.y; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices, worldVertices = this.worldVertices; + var bones = this.bones; + if (bones == null) { + var verticesLength = vertices.length; + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + x += bone.worldX; + y += bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v = 0, w = 0; v < verticesLength; v += 2, w += 8) { + var vx = vertices[v], vy = vertices[v + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + return worldVertices; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = 0, v = 0, b = 0, n = bones.length; v < n; w += 8) { + var wx = x, wy = y; + var nn = bones[v++] + v; + for (; v < nn; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + } + else { + var deform = deformArray; + for (var w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 8) { + var wx = x, wy = y; + var nn = bones[v++] + v; + for (; v < nn; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + } + return worldVertices; + }; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + } + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + _super.call(this, name); + this.closed = false; + this.constantSpeed = false; + this.color = new spine.Color(1, 1, 1, 1); + } + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + _super.call(this, name); + this.x = 0; + this.y = 0; + this.scaleX = 1; + this.scaleY = 1; + this.rotation = 0; + this.width = 0; + this.height = 0; + this.color = new spine.Color(1, 1, 1, 1); + this.offset = spine.Utils.newFloatArray(8); + this.vertices = spine.Utils.newFloatArray(8 * 4); + this.tempColor = new spine.Color(1, 1, 1, 1); + } + RegionAttachment.prototype.setRegion = function (region) { + var vertices = this.vertices; + if (region.rotate) { + vertices[RegionAttachment.U2] = region.u; + vertices[RegionAttachment.V2] = region.v2; + vertices[RegionAttachment.U3] = region.u; + vertices[RegionAttachment.V3] = region.v; + vertices[RegionAttachment.U4] = region.u2; + vertices[RegionAttachment.V4] = region.v; + vertices[RegionAttachment.U1] = region.u2; + vertices[RegionAttachment.V1] = region.v2; + } + else { + vertices[RegionAttachment.U1] = region.u; + vertices[RegionAttachment.V1] = region.v2; + vertices[RegionAttachment.U2] = region.u; + vertices[RegionAttachment.V2] = region.v; + vertices[RegionAttachment.U3] = region.u2; + vertices[RegionAttachment.V3] = region.v; + vertices[RegionAttachment.U4] = region.u2; + vertices[RegionAttachment.V4] = region.v2; + } + this.region = region; + }; + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = this.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var 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); + var vertices = this.vertices; + var offset = this.offset; + var bone = slot.bone; + var x = skeleton.x + bone.worldX, y = skeleton.y + bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = offset[RegionAttachment.OX1]; + offsetY = offset[RegionAttachment.OY1]; + vertices[RegionAttachment.X1] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y1] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + offsetX = offset[RegionAttachment.OX2]; + offsetY = offset[RegionAttachment.OY2]; + vertices[RegionAttachment.X2] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y2] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + offsetX = offset[RegionAttachment.OX3]; + offsetY = offset[RegionAttachment.OY3]; + vertices[RegionAttachment.X3] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y3] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + offsetX = offset[RegionAttachment.OX4]; + offsetY = offset[RegionAttachment.OY4]; + vertices[RegionAttachment.X4] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y4] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + return vertices; + }; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(spine.BlendMode || (spine.BlendMode = {})); + var BlendMode = spine.BlendMode; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.appliedRotation = 0; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.worldSignX = 0; + this.worldSignY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.appliedRotation = rotation; + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX, lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX, ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + var parent = this.parent; + if (parent == null) { + var skeleton = this.skeleton; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (skeleton.flipY) { + y = -y; + lc = -lc; + ld = -ld; + } + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + this.worldX = x; + this.worldY = y; + this.worldSignX = spine.MathUtils.signum(scaleX); + this.worldSignY = spine.MathUtils.signum(scaleY); + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + this.worldSignX = parent.worldSignX * spine.MathUtils.signum(scaleX); + this.worldSignY = parent.worldSignY * spine.MathUtils.signum(scaleY); + if (this.data.inheritRotation && this.data.inheritScale) { + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + } + else { + if (this.data.inheritRotation) { + pa = 1; + pb = 0; + pc = 0; + pd = 1; + do { + var cos = spine.MathUtils.cosDeg(parent.appliedRotation), sin = spine.MathUtils.sinDeg(parent.appliedRotation); + var temp = pa * cos + pb * sin; + pb = pb * cos - pa * sin; + pa = temp; + temp = pc * cos + pd * sin; + pd = pd * cos - pc * sin; + pc = temp; + if (!parent.data.inheritRotation) + break; + parent = parent.parent; + } while (parent != null); + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + } + else if (this.data.inheritScale) { + pa = 1; + pb = 0; + pc = 0; + pd = 1; + do { + var cos = spine.MathUtils.cosDeg(parent.appliedRotation), sin = spine.MathUtils.sinDeg(parent.appliedRotation); + var psx = parent.scaleX, psy = parent.scaleY; + var za = cos * psx, zb = sin * psy, zc = sin * psx, zd = cos * psy; + var temp = pa * za + pb * zc; + pb = pb * zd - pa * zb; + pa = temp; + temp = pc * za + pd * zc; + pd = pd * zd - pc * zb; + pc = temp; + if (psx >= 0) + sin = -sin; + temp = pa * cos + pb * sin; + pb = pb * cos - pa * sin; + pa = temp; + temp = pc * cos + pd * sin; + pd = pd * cos - pc * sin; + pc = temp; + if (!parent.data.inheritScale) + break; + parent = parent.parent; + } while (parent != null); + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + } + else { + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + } + if (this.skeleton.flipX) { + this.a = -this.a; + this.b = -this.b; + } + if (this.skeleton.flipY) { + this.c = -this.c; + this.d = -this.d; + } + } + }; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + }; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.b * this.b) * this.worldSignX; + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.c * this.c + this.d * this.d) * this.worldSignY; + }; + Bone.prototype.worldToLocalRotationX = function () { + var parent = this.parent; + if (parent == null) + return this.rotation; + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; + return Math.atan2(pa * c - pc * a, pd * a - pb * c) * spine.MathUtils.radDeg; + }; + Bone.prototype.worldToLocalRotationY = function () { + var parent = this.parent; + if (parent == null) + return this.rotation; + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; + return Math.atan2(pa * d - pc * b, pd * b - pb * d) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + }; + Bone.prototype.updateLocalTransform = function () { + var parent = this.parent; + if (parent == null) { + this.x = this.worldX; + this.y = this.worldY; + this.rotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.scaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.scaleY = Math.sqrt(this.b * this.b + this.d * this.d); + var det = this.a * this.d - this.b * this.c; + this.shearX = 0; + this.shearY = Math.atan2(this.a * this.b + this.c * this.d, det) * spine.MathUtils.radDeg; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.x = (dx * pd * pid - dy * pb * pid); + this.y = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.shearX = 0; + this.scaleX = Math.sqrt(ra * ra + rc * rc); + if (this.scaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.scaleY = det / this.scaleX; + this.shearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.rotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + } + else { + this.scaleX = 0; + this.scaleY = Math.sqrt(rb * rb + rd * rd); + this.shearY = 0; + this.rotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; + } + this.appliedRotation = this.rotation; + }; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; + }; + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + }; + return Bone; + }()); + spine.Bone = Bone; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoneData = (function () { + function BoneData(index, name, parent) { + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.inheritRotation = true; + this.inheritScale = true; + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + return BoneData; + }()); + spine.BoneData = BoneData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; +})(spine || (spine = {})); +var spine; +(function (spine) { + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.mix = 1; + this.bendDirection = 0; + this.level = 0; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.bendDirection = data.bendDirection; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + IkConstraint.prototype.apply = function () { + this.update(); + }; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); + break; + } + }; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) { + var pp = bone.parent; + var id = 1 / (pp.a * pp.d - pp.b * pp.c); + var x = targetX - pp.worldX, y = targetY - pp.worldY; + var tx = (x * pp.d - y * pp.b) * id - bone.x, ty = (y * pp.a - x * pp.c) * id - bone.y; + var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.shearX - bone.rotation; + if (bone.scaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + bone.updateWorldTransformWith(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX, bone.shearY); + }; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + var px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } + else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } + else + os2 = 0; + var cx = child.x, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + var u = Math.abs(psx - psy) <= 0.0001; + if (!u) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } + else { + cy = child.y; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + var pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + var id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; + var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + x = cwx - pp.worldX; + y = cwy - pp.worldY; + var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1 = 0, a2 = 0; + outer: if (u) { + l2 *= psx; + var cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + cos = -1; + else if (cos > 1) + cos = 1; + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } + else { + a = psx * l2; + b = psy * l2; + var aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + var c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + var q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) / 2; + var r0 = q / c2, r1 = c / q; + var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + var minAngle = 0, minDist = Number.MAX_VALUE, minX = 0, minY = 0; + var maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; + x = l1 + a; + d = x * x; + if (d > maxDist) { + maxAngle = 0; + maxDist = d; + maxX = x; + } + x = l1 - a; + d = x * x; + if (d < minDist) { + minAngle = spine.MathUtils.PI; + minDist = d; + minX = x; + } + var angle = Math.acos(-a * l1 / (aa - bb)); + x = a * Math.cos(angle) + l1; + y = b * Math.sin(angle); + d = x * x + y * y; + if (d < minDist) { + minAngle = angle; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = angle; + maxDist = d; + maxX = x; + maxY = y; + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + var os = Math.atan2(cy, cx) * s2; + var rotation = parent.rotation; + a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0); + rotation = child.rotation; + a2 = ((a2 + os) * spine.MathUtils.radDeg - child.shearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY); + }; + return IkConstraint; + }()); + spine.IkConstraint = IkConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraintData = (function () { + function IkConstraintData(name) { + this.bones = new Array(); + this.bendDirection = 1; + this.mix = 1; + this.name = name; + } + return IkConstraintData; + }()); + spine.IkConstraintData = IkConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraint = (function () { + function PathConstraint(data, skeleton) { + this.position = 0; + this.spacing = 0; + this.rotateMix = 0; + this.translateMix = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + } + PathConstraint.prototype.apply = function () { + this.update(); + }; + PathConstraint.prototype.update = function () { + var attachment = this.target.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + return; + var rotateMix = this.rotateMix, translateMix = this.translateMix; + var translate = translateMix > 0, rotate = rotateMix > 0; + if (!translate && !rotate) + return; + var data = this.data; + var spacingMode = data.spacingMode; + var lengthSpacing = spacingMode == spine.SpacingMode.Length; + var rotateMode = data.rotateMode; + var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale; + var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + var bones = this.bones; + var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null; + var spacing = this.spacing; + if (scale || lengthSpacing) { + if (scale) + lengths = spine.Utils.setArraySize(this.lengths, boneCount); + for (var i = 0, n = spacesCount - 1; i < n;) { + var bone = bones[i]; + var length_1 = bone.data.length, x = length_1 * bone.a, y = length_1 * bone.c; + length_1 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_1; + spaces[++i] = lengthSpacing ? Math.max(0, length_1 + spacing) : spacing; + } + } + else { + for (var i = 1; i < spacesCount; i++) + spaces[i] = spacing; + } + var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, spacingMode == spine.SpacingMode.Percent); + var skeleton = this.target.bone.skeleton; + var skeletonX = skeleton.x, skeletonY = skeleton.y; + var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + var tip = rotateMode == spine.RotateMode.Chain && offsetRotation == 0; + for (var i = 0, p = 3; i < boneCount; i++, p += 3) { + var bone = bones[i]; + bone.worldX += (boneX - skeletonX - bone.worldX) * translateMix; + bone.worldY += (boneY - skeletonY - bone.worldY) * translateMix; + var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + var length_2 = lengths[i]; + if (length_2 != 0) { + var s = (Math.sqrt(dx * dx + dy * dy) / length_2 - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (rotate) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a) - offsetRotation * spine.MathUtils.degRad; + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + var length_3 = bone.data.length; + boneX += (length_3 * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length_3 * (sin * a + cos * c) - dy) * rotateMix; + } + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + } + }; + PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) { + var target = this.target; + var position = this.position; + var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + var closed = path.closed; + var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; + if (!path.constantSpeed) { + var lengths = path.lengths; + curveCount -= closed ? 1 : 2; + var pathLength_1 = lengths[curveCount]; + if (percentPosition) + position *= pathLength_1; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength_1; + } + world = spine.Utils.setArraySize(this.world, 8); + for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength_1; + if (p < 0) + p += pathLength_1; + curve = 0; + } + else if (p < 0) { + if (prevCurve != PathConstraint.BEFORE) { + prevCurve = PathConstraint.BEFORE; + path.computeWorldVerticesWith(target, 2, 4, world, 0); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength_1) { + if (prevCurve != PathConstraint.AFTER) { + prevCurve = PathConstraint.AFTER; + path.computeWorldVerticesWith(target, verticesLength - 6, 4, world, 0); + } + this.addAfterPosition(p - pathLength_1, world, 0, out, o); + continue; + } + for (;; curve++) { + var length_4 = lengths[curve]; + if (p > length_4) + continue; + if (curve == 0) + p /= length_4; + else { + var prev = lengths[curve - 1]; + p = (p - prev) / (length_4 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVerticesWith(target, verticesLength - 4, 4, world, 0); + path.computeWorldVerticesWith(target, 0, 4, world, 4); + } + else + path.computeWorldVerticesWith(target, curve * 6 + 2, 8, world, 0); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); + } + return out; + } + if (closed) { + verticesLength += 2; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVerticesWith(target, 2, verticesLength - 4, world, 0); + path.computeWorldVerticesWith(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else { + curveCount--; + verticesLength -= 4; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVerticesWith(target, 2, verticesLength, world, 0); + } + var curves = spine.Utils.setArraySize(this.curves, curveCount); + var pathLength = 0; + var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (var i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (percentPosition) + position *= pathLength; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength; + } + var segments = this.segments; + var curveLength = 0; + for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } + else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (;; curve++) { + var length_5 = curves[curve]; + if (p > length_5) + continue; + if (curve == 0) + p /= length_5; + else { + var prev = curves[curve - 1]; + p = (p - prev) / (length_5 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + var ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (;; segment++) { + var length_6 = segments[segment]; + if (p > length_6) + continue; + if (segment == 0) + p /= length_6; + else { + var prev = segments[segment - 1]; + p = segment + (p - prev) / (length_6 - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + } + return out; + }; + PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) { + var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) { + var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0) + p = 0.0001; + var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + }; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + return PathConstraint; + }()); + spine.PathConstraint = PathConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraintData = (function () { + function PathConstraintData(name) { + this.bones = new Array(); + this.name = name; + } + return PathConstraintData; + }()); + spine.PathConstraintData = PathConstraintData; + (function (PositionMode) { + PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; + PositionMode[PositionMode["Percent"] = 1] = "Percent"; + })(spine.PositionMode || (spine.PositionMode = {})); + var PositionMode = spine.PositionMode; + (function (SpacingMode) { + SpacingMode[SpacingMode["Length"] = 0] = "Length"; + SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; + SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; + })(spine.SpacingMode || (spine.SpacingMode = {})); + var SpacingMode = spine.SpacingMode; + (function (RotateMode) { + RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; + RotateMode[RotateMode["Chain"] = 1] = "Chain"; + RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; + })(spine.RotateMode || (spine.RotateMode = {})); + var RotateMode = spine.RotateMode; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Assets = (function () { + function Assets(clientId) { + this.toLoad = new Array(); + this.assets = {}; + this.clientId = clientId; + } + Assets.prototype.loaded = function () { + var i = 0; + for (var v in this.assets) + i++; + return i; + }; + return Assets; + }()); + var SharedAssetManager = (function () { + function SharedAssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.clientAssets = {}; + this.queuedAssets = {}; + this.rawAssets = {}; + this.errors = {}; + this.pathPrefix = pathPrefix; + } + SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) { + clientAssets = new Assets(clientId); + this.clientAssets[clientId] = clientAssets; + } + if (textureLoader !== null) + clientAssets.textureLoader = textureLoader; + clientAssets.toLoad.push(path); + if (this.queuedAssets[path] === path) { + return false; + } + else { + this.queuedAssets[path] = path; + return true; + } + }; + SharedAssetManager.prototype.loadText = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = request.responseText; + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadJson = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = JSON.parse(request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, textureLoader, path)) + return; + var img = new Image(); + img.src = path; + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + _this.rawAssets[path] = img; + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + }; + }; + SharedAssetManager.prototype.get = function (clientId, path) { + path = this.pathPrefix + path; + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + return clientAssets.assets[path]; + }; + SharedAssetManager.prototype.updateClientAssets = function (clientAssets) { + for (var i = 0; i < clientAssets.toLoad.length; i++) { + var path = clientAssets.toLoad[i]; + var asset = clientAssets.assets[path]; + if (asset === null || asset === undefined) { + var rawAsset = this.rawAssets[path]; + if (rawAsset === null || rawAsset === undefined) + continue; + if (rawAsset instanceof HTMLImageElement) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + } + }; + SharedAssetManager.prototype.isLoadingComplete = function (clientId) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + this.updateClientAssets(clientAssets); + return clientAssets.toLoad.length == clientAssets.loaded(); + }; + SharedAssetManager.prototype.dispose = function () { + }; + SharedAssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + SharedAssetManager.prototype.getErrors = function () { + return this.errors; + }; + return SharedAssetManager; + }()); + spine.SharedAssetManager = SharedAssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skeleton = (function () { + function Skeleton(data) { + this._updateCache = new Array(); + this.time = 0; + this.flipX = false; + this.flipY = false; + this.x = 0; + this.y = 0; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) { + var boneData = data.bones[i]; + var bone = void 0; + if (boneData.parent == null) + bone = new spine.Bone(boneData, this, null); + else { + var parent_1 = this.bones[boneData.parent.index]; + bone = new spine.Bone(boneData, this, parent_1); + parent_1.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (var i = 0; i < data.slots.length; i++) { + var slotData = data.slots[i]; + var bone = this.bones[slotData.boneData.index]; + var slot = new spine.Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + this.ikConstraintsSorted = new Array(); + for (var i = 0; i < data.ikConstraints.length; i++) { + var ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (var i = 0; i < data.transformConstraints.length; i++) { + var transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (var i = 0; i < data.pathConstraints.length; i++) { + var pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this)); + } + this.color = new spine.Color(1, 1, 1, 1); + this.updateCache(); + } + Skeleton.prototype.updateCache = function () { + var updateCache = this._updateCache; + updateCache.length = 0; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].sorted = false; + var ikConstraints = this.ikConstraintsSorted; + ikConstraints.length = 0; + for (var i = 0; i < this.ikConstraints.length; i++) + ikConstraints.push(this.ikConstraints[i]); + var ikCount = ikConstraints.length; + for (var i = 0, level = 0, n = ikCount; i < n; i++) { + var ik = ikConstraints[i]; + var bone = ik.bones[0].parent; + for (level = 0; bone != null; level++) + bone = bone.parent; + ik.level = level; + } + for (var i = 1, ii = 0; i < ikCount; i++) { + var ik = ikConstraints[i]; + var level = ik.level; + for (ii = i - 1; ii >= 0; ii--) { + var other = ikConstraints[ii]; + if (other.level < level) + break; + ikConstraints[ii + 1] = other; + } + ikConstraints[ii + 1] = ik; + } + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + var target = constraint.target; + this.sortBone(target); + var constrained = constraint.bones; + var parent_2 = constrained[0]; + this.sortBone(parent_2); + updateCache.push(constraint); + this.sortReset(parent_2.children); + constrained[constrained.length - 1].sorted = true; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var slot = constraint.target; + var slotIndex = slot.data.index; + var slotBone = slot.bone; + if (this.skin != null) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (var ii = 0, nn = this.data.skins.length; ii < nn; ii++) + this.sortPathConstraintAttachment(this.data.skins[ii], slotIndex, slotBone); + var attachment = slot.getAttachment(); + if (attachment instanceof spine.PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var ii = 0; ii < boneCount; ii++) + this.sortBone(constrained[ii]); + updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + this.sortBone(constraint.target); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var ii = 0; ii < boneCount; ii++) + this.sortBone(constrained[ii]); + updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + } + for (var i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + }; + Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) { + var attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (var key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + }; + Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) { + if (!(attachment instanceof spine.PathAttachment)) + return; + var pathBones = attachment.bones; + if (pathBones == null) + this.sortBone(slotBone); + else { + var bones = this.bones; + var i = 0; + while (i < pathBones.length) { + var boneCount = pathBones[i++]; + for (var n = i + boneCount; i < n; i++) { + var boneIndex = pathBones[i]; + this.sortBone(bones[boneIndex]); + } + } + } + }; + Skeleton.prototype.sortBone = function (bone) { + if (bone.sorted) + return; + var parent = bone.parent; + if (parent != null) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + }; + Skeleton.prototype.sortReset = function (bones) { + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + }; + Skeleton.prototype.updateWorldTransform = function () { + var updateCache = this._updateCache; + for (var i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + }; + Skeleton.prototype.setToSetupPose = function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }; + Skeleton.prototype.setBonesToSetupPose = function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + constraint.bendDirection = constraint.data.bendDirection; + constraint.mix = constraint.data.mix; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + } + }; + Skeleton.prototype.setSlotsToSetupPose = function () { + var slots = this.slots; + spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + }; + Skeleton.prototype.getRootBone = function () { + if (this.bones.length == 0) + return null; + return this.bones[0]; + }; + Skeleton.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + }; + Skeleton.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) + return i; + return -1; + }; + Skeleton.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + }; + Skeleton.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) + return i; + return -1; + }; + Skeleton.prototype.setSkinByName = function (skinName) { + var skin = this.data.findSkin(skinName); + if (skin == null) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + }; + Skeleton.prototype.setSkin = function (newSkin) { + if (newSkin != null) { + if (this.skin != null) + newSkin.attachAll(this, this.skin); + else { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var name_1 = slot.data.attachmentName; + if (name_1 != null) { + var attachment = newSkin.getAttachment(i, name_1); + if (attachment != null) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + }; + Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) { + return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName); + }; + Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) { + if (attachmentName == null) + throw new Error("attachmentName cannot be null."); + if (this.skin != null) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + return attachment; + } + if (this.data.defaultSkin != null) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }; + Skeleton.prototype.setAttachment = function (slotName, attachmentName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName != null) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + }; + Skeleton.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + }; + Skeleton.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.getBounds = function (offset, size) { + if (offset == null) + throw new Error("offset cannot be null."); + if (size == null) + throw new Error("size cannot be null."); + var drawOrder = this.drawOrder; + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var vertices = null; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) + vertices = attachment.updateWorldVertices(slot, false); + else if (attachment instanceof spine.MeshAttachment) + vertices = attachment.updateWorldVertices(slot, true); + if (vertices != null) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 8) { + var x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + }; + Skeleton.prototype.update = function (delta) { + this.time += delta; + }; + return Skeleton; + }()); + spine.Skeleton = Skeleton; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBounds = (function () { + function SkeletonBounds() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new spine.Pool(function () { + return spine.Utils.newFloatArray(16); + }); + } + SkeletonBounds.prototype.update = function (skeleton, updateAabb) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + var boundingBoxes = this.boundingBoxes; + var polygons = this.polygons; + var polygonPool = this.polygonPool; + var slots = skeleton.slots; + var slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (var i = 0; i < slotCount; i++) { + var slot = slots[i]; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.BoundingBoxAttachment) { + var boundingBox = attachment; + boundingBoxes.push(boundingBox); + var polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, polygon); + } + } + if (updateAabb) + this.aabbCompute(); + }; + SkeletonBounds.prototype.aabbCompute = function () { + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + var vertices = polygon; + for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) { + var x = vertices[ii]; + var y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + }; + SkeletonBounds.prototype.aabbContainsPoint = function (x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + }; + SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) { + var minX = this.minX; + var minY = this.minY; + var maxX = this.maxX; + var maxY = this.maxY; + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + return false; + var m = (y2 - y1) / (x2 - x1); + var y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + var x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + }; + SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + }; + SkeletonBounds.prototype.containsPoint = function (x, y) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) { + var vertices = polygon; + var nn = polygon.length; + var prevIndex = nn - 2; + var inside = false; + for (var ii = 0; ii < nn; ii += 2) { + var vertexY = vertices[ii + 1]; + var prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + var vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + }; + SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) { + var vertices = polygon; + var nn = polygon.length; + var width12 = x1 - x2, height12 = y1 - y2; + var det1 = x1 * y2 - y1 * x2; + var x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (var ii = 0; ii < nn; ii += 2) { + var x4 = vertices[ii], y4 = vertices[ii + 1]; + var det2 = x3 * y4 - y3 * x4; + var width34 = x3 - x4, height34 = y3 - y4; + var det3 = width12 * height34 - height12 * width34; + var x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + var y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + }; + SkeletonBounds.prototype.getPolygon = function (boundingBox) { + if (boundingBox == null) + throw new Error("boundingBox cannot be null."); + var index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + }; + SkeletonBounds.prototype.getWidth = function () { + return this.maxX - this.minX; + }; + SkeletonBounds.prototype.getHeight = function () { + return this.maxY - this.minY; + }; + return SkeletonBounds; + }()); + spine.SkeletonBounds = SkeletonBounds; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonData = (function () { + function SkeletonData() { + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + } + SkeletonData.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + }; + SkeletonData.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) + return i; + return -1; + }; + SkeletonData.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + }; + SkeletonData.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) + return i; + return -1; + }; + SkeletonData.prototype.findSkin = function (skinName) { + if (skinName == null) + throw new Error("skinName cannot be null."); + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) { + var skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + }; + SkeletonData.prototype.findEvent = function (eventDataName) { + if (eventDataName == null) + throw new Error("eventDataName cannot be null."); + var events = this.events; + for (var i = 0, n = events.length; i < n; i++) { + var event_2 = events[i]; + if (event_2.name == eventDataName) + return event_2; + } + return null; + }; + SkeletonData.prototype.findAnimation = function (animationName) { + if (animationName == null) + throw new Error("animationName cannot be null."); + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) { + var animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + }; + SkeletonData.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) { + if (pathConstraintName == null) + throw new Error("pathConstraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) + if (pathConstraints[i].name == pathConstraintName) + return i; + return -1; + }; + return SkeletonData; + }()); + spine.SkeletonData = SkeletonData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonJson = (function () { + function SkeletonJson(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonJson.prototype.readSkeletonData = function (json) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + var root = typeof (json) === "string" ? JSON.parse(json) : json; + var skeletonMap = root.skeleton; + if (skeletonMap != null) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (var i = 0; i < root.bones.length; i++) { + var boneMap = root.bones[i]; + var parent_3 = null; + var parentName = this.getValue(boneMap, "parent", null); + if (parentName != null) { + parent_3 = skeletonData.findBone(parentName); + if (parent_3 == null) + throw new Error("Parent bone not found: " + parentName); + } + var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_3); + data.length = this.getValue(boneMap, "length", 0) * scale; + data.x = this.getValue(boneMap, "x", 0) * scale; + data.y = this.getValue(boneMap, "y", 0) * scale; + data.rotation = this.getValue(boneMap, "rotation", 0); + data.scaleX = this.getValue(boneMap, "scaleX", 1); + data.scaleY = this.getValue(boneMap, "scaleY", 1); + data.shearX = this.getValue(boneMap, "shearX", 0); + data.shearY = this.getValue(boneMap, "shearY", 0); + data.inheritRotation = this.getValue(boneMap, "inheritRotation", true); + data.inheritScale = this.getValue(boneMap, "inheritScale", true); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (var i = 0; i < root.slots.length; i++) { + var slotMap = root.slots[i]; + var slotName = slotMap.name; + var boneName = slotMap.bone; + var boneData = skeletonData.findBone(boneName); + if (boneData == null) + throw new Error("Slot bone not found: " + boneName); + var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData); + var color = this.getValue(slotMap, "color", null); + if (color != null) + data.color.setFromString(color); + data.attachmentName = this.getValue(slotMap, "attachment", null); + data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (var i = 0; i < root.ik.length; i++) { + var constraintMap = root.ik[i]; + var data = new spine.IkConstraintData(constraintMap.name); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("IK bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("IK target bone not found: " + targetName); + data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.mix = this.getValue(constraintMap, "mix", 1); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (var i = 0; i < root.transform.length; i++) { + var constraintMap = root.transform[i]; + var data = new spine.TransformConstraintData(constraintMap.name); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("Transform constraint target bone not found: " + targetName); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.offsetX = this.getValue(constraintMap, "x", 0) * scale; + data.offsetY = this.getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0); + data.offsetShearY = this.getValue(constraintMap, "shearY", 0); + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + data.scaleMix = this.getValue(constraintMap, "scaleMix", 1); + data.shearMix = this.getValue(constraintMap, "shearMix", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (var i = 0; i < root.path.length; i++) { + var constraintMap = root.path[i]; + var data = new spine.PathConstraintData(constraintMap.name); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + if (data.target == null) + throw new Error("Path target slot not found: " + targetName); + data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent")); + data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length")); + data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent")); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.position = this.getValue(constraintMap, "position", 0); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = this.getValue(constraintMap, "spacing", 0); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (var skinName in root.skins) { + var skinMap = root.skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + var slotMap = skinMap[slotName]; + for (var entryName in slotMap) { + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); + if (attachment != null) + skin.addAttachment(slotIndex, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (var i = 0, n = this.linkedMeshes.length; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_4 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_4 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.setParentMesh(parent_4); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (var eventName in root.events) { + var eventMap = root.events[eventName]; + var data = new spine.EventData(eventName); + data.intValue = this.getValue(eventMap, "int", 0); + data.floatValue = this.getValue(eventMap, "float", 0); + data.stringValue = this.getValue(eventMap, "string", null); + skeletonData.events.push(data); + } + } + if (root.animations) { + for (var animationName in root.animations) { + var animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + }; + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { + var scale = this.scale; + name = this.getValue(map, "name", name); + var type = this.getValue(map, "type", "region"); + switch (type) { + case "region": { + var path = this.getValue(map, "path", name); + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = this.getValue(map, "x", 0) * scale; + region.y = this.getValue(map, "y", 0) * scale; + region.scaleX = this.getValue(map, "scaleX", 1); + region.scaleY = this.getValue(map, "scaleY", 1); + region.rotation = this.getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + var color = this.getValue(map, "color", null); + if (color != null) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + this.readVertices(map, box, map.vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + var path = this.getValue(map, "path", name); + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + var color = this.getValue(map, "color", null); + if (color != null) + mesh.color.setFromString(color); + var parent_5 = this.getValue(map, "parent", null); + if (parent_5 != null) { + mesh.inheritDeform = this.getValue(map, "deform", true); + this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_5)); + return mesh; + } + var uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = this.getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = this.getValue(map, "closed", false); + path.constantSpeed = this.getValue(map, "constantSpeed", true); + var vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + var color = this.getValue(map, "color", null); + if (color != null) + path.color.setFromString(color); + return path; + } + } + return null; + }; + SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) { + var scale = this.scale; + attachment.worldVerticesLength = verticesLength; + var vertices = map.vertices; + if (verticesLength == vertices.length) { + if (scale != 1) { + for (var i = 0, n = vertices.length; i < n; i++) + vertices[i] *= scale; + } + attachment.vertices = spine.Utils.toFloatArray(vertices); + return; + } + var weights = new Array(); + var bones = new Array(); + for (var i = 0, n = vertices.length; i < n;) { + var boneCount = vertices[i++]; + bones.push(boneCount); + for (var nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = spine.Utils.toFloatArray(weights); + }; + SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) { + var scale = this.scale; + var timelines = new Array(); + var duration = 0; + if (map.slots) { + for (var slotName in map.slots) { + var slotMap = map.slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + if (timelineName == "color") { + var timeline = new spine.ColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var color = new spine.Color(); + color.setFromString(valueMap.color); + timeline.setFrame(frameIndex, valueMap.time, color.r, color.g, color.b, color.a); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); + } + else if (timelineName = "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else + throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + if (map.bones) { + for (var boneName in map.bones) { + var boneMap = map.bones[boneName]; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) + throw new Error("Bone not found: " + boneName); + for (var timelineName in boneMap) { + var timelineMap = boneMap[timelineName]; + if (timelineName === "rotate") { + var timeline = new spine.RotateTimeline(timelineMap.length); + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, valueMap.angle); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]); + } + else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "scale") + timeline = new spine.ScaleTimeline(timelineMap.length); + else if (timelineName === "shear") + timeline = new spine.ShearTimeline(timelineMap.length); + else { + timeline = new spine.TranslateTimeline(timelineMap.length); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var x = this.getValue(valueMap, "x", 0), y = this.getValue(valueMap, "y", 0); + timeline.setFrame(frameIndex, valueMap.time, x * timelineScale, y * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); + } + } + } + if (map.ik) { + for (var constraintName in map.ik) { + var constraintMap = map.ik[constraintName]; + var constraint = skeletonData.findIkConstraint(constraintName); + var timeline = new spine.IkConstraintTimeline(constraintMap.length); + timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + } + if (map.transform) { + for (var constraintName in map.transform) { + var constraintMap = map.transform[constraintName]; + var constraint = skeletonData.findTransformConstraint(constraintName); + var timeline = new spine.TransformConstraintTimeline(constraintMap.length); + timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + } + if (map.paths) { + for (var constraintName in map.paths) { + var constraintMap = map.paths[constraintName]; + var index = skeletonData.findPathConstraintIndex(constraintName); + if (index == -1) + throw new Error("Path constraint not found: " + constraintName); + var data = skeletonData.pathConstraints[index]; + for (var timelineName in constraintMap) { + var timelineMap = constraintMap[timelineName]; + if (timelineName === "position" || timelineName === "spacing") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "spacing") { + timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(timelineMap.length); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, timelineName, 0) * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + } + else if (timelineName === "mix") { + var timeline = new spine.PathConstraintMixTimeline(timelineMap.length); + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + } + } + } + } + if (map.deform) { + for (var deformName in map.deform) { + var deformMap = map.deform[deformName]; + var skin = skeletonData.findSkin(deformName); + if (skin == null) + throw new Error("Skin not found: " + deformName); + for (var slotName in deformMap) { + var slotMap = deformMap[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotMap.name); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + var attachment = skin.getAttachment(slotIndex, timelineName); + if (attachment == null) + throw new Error("Deform attachment not found: " + timelineMap.name); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var timeline = new spine.DeformTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + var frameIndex = 0; + for (var j = 0; j < timelineMap.length; j++) { + var valueMap = timelineMap[j]; + var deform = void 0; + var verticesValue = this.getValue(valueMap, "vertices", null); + if (verticesValue == null) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = this.getValue(valueMap, "offset", 0); + spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (var i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (var i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frameIndex, valueMap.time, deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_3 = new spine.Event(eventMap.time, eventData); + event_3.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_3.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_3.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + timeline.setFrame(frameIndex++, event_3); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.curve) + return; + if (map.curve === "stepped") + timeline.setStepped(frameIndex); + else if (Object.prototype.toString.call(map.curve) === '[object Array]') { + var curve = map.curve; + timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.addAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.attachmentVertices = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.attachmentVertices.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + region.rotate = reader.readValue() == "true"; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + _super.apply(this, arguments); + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlasAttachmentLoader = (function () { + function TextureAtlasAttachmentLoader(atlas) { + this.atlas = atlas; + } + TextureAtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.RegionAttachment(name); + attachment.setRegion(region); + return attachment; + }; + TextureAtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.MeshAttachment(name); + attachment.region = region; + return attachment; + }; + TextureAtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) { + return new spine.BoundingBoxAttachment(name); + }; + TextureAtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { + return new spine.PathAttachment(name); + }; + return TextureAtlasAttachmentLoader; + }()); + spine.TextureAtlasAttachmentLoader = TextureAtlasAttachmentLoader; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (rotateMix > 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + this.data.offsetRotation * spine.MathUtils.degRad; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translateMix > 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + } + if (scaleMix > 0) { + var bs = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + var s = bs > 0.00001 ? (bs + (ts - bs + this.data.offsetScaleX) * scaleMix) / bs : 0; + bone.a *= s; + bone.c *= s; + bs = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + s = bs > 0.00001 ? (bs + (ts - bs + this.data.offsetScaleY) * scaleMix) / bs : 0; + bone.b *= s; + bone.d *= s; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + this.data.offsetShearY * spine.MathUtils.degRad) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + } + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function () { + function TransformConstraintData(name) { + this.bones = new Array(); + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return TransformConstraintData; + }()); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + }; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + }; + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + }; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; + }()); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { + } + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); + }; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); + }; + MathUtils.signum = function (value) { + return value >= 0 ? 1 : -1; + }; + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + }; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + }; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; + }()); + spine.MathUtils = MathUtils; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; + } + return array; + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; + }()); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { + } + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + }; + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + }; + Pool.prototype.free = function (item) { + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) + this.items[i] = items[i]; + }; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; + }()); + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; + } + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; + }()); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; + } + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + }; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; +})(spine || (spine = {})); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/lib/3.5/README.md b/release/MAC版本/lib/3.5/README.md new file mode 100644 index 0000000..8b2d67c --- /dev/null +++ b/release/MAC版本/lib/3.5/README.md @@ -0,0 +1,11 @@ +# Spine 3.5 + +Official `3.5.51` tag, commit `2cd9467d2736b7f3a0b81382f117c73823bfb44b`, `spine-ts/build/spine-canvas.js`. The branch named `3.5` contains later 3.6 beta data; this bundle deliberately uses the tag. + +Local correction: the path-length loop uses `lengths[i]` instead of `lengths[i++]`, avoiding a double increment and NaN values. + +The binary compatibility layer reads 3.5 transform modes and constraint order, but does not read 3.6 dark-slot color or local/relative transform fields. Rendering uses the older attachment vertex interface. The version predates clipping attachments. + +The official tag includes matching 3.5.03-beta JSON/SKEL pairs for seven variants. Tank and Raptor have 3.5.49 JSON but 3.5.03-beta SKEL; these are tested independently, not compared as identical exports. No version strings or data are rewritten. + +License: `LICENSES/Spine-3.5-License.txt`. diff --git a/release/MAC版本/lib/3.5/spine-canvas.js b/release/MAC版本/lib/3.5/spine-canvas.js new file mode 100644 index 0000000..c3c8e0a --- /dev/null +++ b/release/MAC版本/lib/3.5/spine-canvas.js @@ -0,0 +1,5539 @@ +var spine; +(function (spine) { + var AssetManager = (function () { + function AssetManager(textureLoader, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + } + AssetManager.prototype.loadText = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.assets[path] = request.responseText; + if (success) + success(path, request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + if (error) + error(path, "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText); + } + _this.toLoad--; + _this.loaded++; + } + }; + request.open("GET", path, true); + request.send(); + }; + AssetManager.prototype.loadTexture = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.crossOrigin = "anonymous"; + img.src = path; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + }; + AssetManager.prototype.get = function (path) { + path = this.pathPrefix + path; + return this.assets[path]; + }; + AssetManager.prototype.remove = function (path) { + path = this.pathPrefix + path; + var asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + this.assets[path] = null; + }; + AssetManager.prototype.removeAll = function () { + for (var key in this.assets) { + var asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + }; + AssetManager.prototype.isLoadingComplete = function () { + return this.toLoad == 0; + }; + AssetManager.prototype.getToLoad = function () { + return this.toLoad; + }; + AssetManager.prototype.getLoaded = function () { + return this.loaded; + }; + AssetManager.prototype.dispose = function () { + this.removeAll(); + }; + AssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + AssetManager.prototype.getErrors = function () { + return this.errors; + }; + return AssetManager; + }()); + spine.AssetManager = AssetManager; +})(spine || (spine = {})); +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + _super.call(this, function (image) { return new spine.canvas.CanvasTexture(image); }, pathPrefix); + } + return AssetManager; + }(spine.AssetManager)); + canvas.AssetManager = AssetManager; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(spine.TextureFilter || (spine.TextureFilter = {})); + var TextureFilter = spine.TextureFilter; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(spine.TextureWrap || (spine.TextureWrap = {})); + var TextureWrap = spine.TextureWrap; + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var CanvasTexture = (function (_super) { + __extends(CanvasTexture, _super); + function CanvasTexture(image) { + _super.call(this, image); + } + CanvasTexture.prototype.setFilters = function (minFilter, magFilter) { }; + CanvasTexture.prototype.setWraps = function (uWrap, vWrap) { }; + CanvasTexture.prototype.dispose = function () { }; + return CanvasTexture; + }(spine.Texture)); + canvas.CanvasTexture = CanvasTexture; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var SkeletonRenderer = (function () { + function SkeletonRenderer(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.tempColor = new spine.Color(0, 0, 0, 1); + this.ctx = context; + } + SkeletonRenderer.prototype.draw = function (skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + }; + SkeletonRenderer.prototype.drawImages = function (skeleton) { + var ctx = this.ctx; + var drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + ctx.save(); + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var regionAttachment = null; + var region = null; + var image = null; + if (attachment instanceof spine.RegionAttachment) { + regionAttachment = attachment; + region = regionAttachment.region; + image = region.texture.getImage(); + } + else + continue; + var skeleton_1 = slot.bone.skeleton; + var skeletonColor = skeleton_1.color; + var slotColor = slot.color; + var regionColor = regionAttachment.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, alpha); + var att = attachment; + var bone = slot.bone; + var w = region.width; + var h = region.height; + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + ctx.scale(attachment.scaleX, attachment.scaleY); + ctx.translate(w / 2, h / 2); + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + if (color.r != 1 || color.g != 1 || color.b != 1 || color.a != 1) { + ctx.globalAlpha = color.a; + } + ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + ctx.restore(); + }; + SkeletonRenderer.prototype.drawTriangles = function (skeleton) { + var blendMode = null; + var vertices = null; + var triangles = null; + var drawOrder = skeleton.drawOrder; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var texture = null; + var region = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = regionAttachment.updateWorldVertices(slot, false); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.texture.getImage(); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + vertices = mesh.updateWorldVertices(slot, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture.getImage(); + } + else + continue; + if (texture != null) { + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + } + var ctx = this.ctx; + for (var j = 0; j < triangles.length; j += 3) { + var t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + var x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + var x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + var 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + }; + SkeletonRenderer.prototype.drawTriangle = function (img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + var ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + return SkeletonRenderer; + }()); + canvas.SkeletonRenderer = SkeletonRenderer; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Animation = (function () { + function Animation(name, timelines, duration) { + if (name == null) + throw new Error("name cannot be null."); + if (timelines == null) + throw new Error("timelines cannot be null."); + this.name = name; + this.timelines = timelines; + this.duration = duration; + } + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, setupPose, mixingOut) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, setupPose, mixingOut); + }; + Animation.binarySearch = function (values, target, step) { + if (step === void 0) { step = 1; } + var low = 0; + var high = values.length / step - 2; + if (high == 0) + return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) + return (low + 1) * step; + current = (low + high) >>> 1; + } + }; + Animation.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) + return i; + return -1; + }; + return Animation; + }()); + spine.Animation = Animation; + (function (TimelineType) { + TimelineType[TimelineType["rotate"] = 0] = "rotate"; + TimelineType[TimelineType["translate"] = 1] = "translate"; + TimelineType[TimelineType["scale"] = 2] = "scale"; + TimelineType[TimelineType["shear"] = 3] = "shear"; + TimelineType[TimelineType["attachment"] = 4] = "attachment"; + TimelineType[TimelineType["color"] = 5] = "color"; + TimelineType[TimelineType["deform"] = 6] = "deform"; + TimelineType[TimelineType["event"] = 7] = "event"; + TimelineType[TimelineType["drawOrder"] = 8] = "drawOrder"; + TimelineType[TimelineType["ikConstraint"] = 9] = "ikConstraint"; + TimelineType[TimelineType["transformConstraint"] = 10] = "transformConstraint"; + TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; + TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; + TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; + })(spine.TimelineType || (spine.TimelineType = {})); + var TimelineType = spine.TimelineType; + var CurveTimeline = (function () { + function CurveTimeline(frameCount) { + if (frameCount <= 0) + throw new Error("frameCount must be > 0: " + frameCount); + this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE); + } + CurveTimeline.prototype.getFrameCount = function () { + return this.curves.length / CurveTimeline.BEZIER_SIZE + 1; + }; + CurveTimeline.prototype.setLinear = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR; + }; + CurveTimeline.prototype.setStepped = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED; + }; + CurveTimeline.prototype.getCurveType = function (frameIndex) { + var index = frameIndex * CurveTimeline.BEZIER_SIZE; + if (index == this.curves.length) + return CurveTimeline.LINEAR; + var type = this.curves[index]; + if (type == CurveTimeline.LINEAR) + return CurveTimeline.LINEAR; + if (type == CurveTimeline.STEPPED) + return CurveTimeline.STEPPED; + return CurveTimeline.BEZIER; + }; + CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) { + var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03; + var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; + var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var curves = this.curves; + curves[i++] = CurveTimeline.BEZIER; + var x = dfx, y = dfy; + for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + }; + CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) { + percent = spine.MathUtils.clamp(percent, 0, 1); + var curves = this.curves; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var type = curves[i]; + if (type == CurveTimeline.LINEAR) + return percent; + if (type == CurveTimeline.STEPPED) + return 0; + i++; + var x = 0; + for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + x = curves[i]; + if (x >= percent) { + var prevX = void 0, prevY = void 0; + if (i == start) { + prevX = 0; + prevY = 0; + } + else { + prevX = curves[i - 2]; + prevY = curves[i - 1]; + } + return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + var y = curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); + }; + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; + return CurveTimeline; + }()); + spine.CurveTimeline = CurveTimeline; + var RotateTimeline = (function (_super) { + __extends(RotateTimeline, _super); + function RotateTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount << 1); + } + RotateTimeline.prototype.getPropertyId = function () { + return (TimelineType.rotate << 24) + this.boneIndex; + }; + RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) { + frameIndex <<= 1; + this.frames[frameIndex] = time; + this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; + }; + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + if (setupPose) + bone.rotation = bone.data.rotation; + return; + } + if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { + if (setupPose) + bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha; + else { + var r_1 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; + r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; + bone.rotation += r_1 * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES); + var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); + var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + r = prevRotation + r * percent; + if (setupPose) { + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.rotation = bone.data.rotation + r * alpha; + } + else { + r = bone.data.rotation + r - bone.rotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.rotation += r * alpha; + } + }; + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; + return RotateTimeline; + }(CurveTimeline)); + spine.RotateTimeline = RotateTimeline; + var TranslateTimeline = (function (_super) { + __extends(TranslateTimeline, _super); + function TranslateTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + } + TranslateTimeline.prototype.getPropertyId = function () { + return (TimelineType.translate << 24) + this.boneIndex; + }; + TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) { + frameIndex *= TranslateTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TranslateTimeline.X] = x; + this.frames[frameIndex + TranslateTimeline.Y] = y; + }; + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + if (setupPose) { + bone.x = bone.data.x; + bone.y = bone.data.y; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) { + x = frames[frames.length + TranslateTimeline.PREV_X]; + y = frames[frames.length + TranslateTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES); + x = frames[frame + TranslateTimeline.PREV_X]; + y = frames[frame + TranslateTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime)); + x += (frames[frame + TranslateTimeline.X] - x) * percent; + y += (frames[frame + TranslateTimeline.Y] - y) * percent; + } + if (setupPose) { + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + } + else { + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + } + }; + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; + return TranslateTimeline; + }(CurveTimeline)); + spine.TranslateTimeline = TranslateTimeline; + var ScaleTimeline = (function (_super) { + __extends(ScaleTimeline, _super); + function ScaleTimeline(frameCount) { + _super.call(this, frameCount); + } + ScaleTimeline.prototype.getPropertyId = function () { + return (TimelineType.scale << 24) + this.boneIndex; + }; + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + if (setupPose) { + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) { + x = frames[frames.length + ScaleTimeline.PREV_X] * bone.data.scaleX; + y = frames[frames.length + ScaleTimeline.PREV_Y] * bone.data.scaleY; + } + else { + var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES); + x = frames[frame + ScaleTimeline.PREV_X]; + y = frames[frame + ScaleTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime)); + x = (x + (frames[frame + ScaleTimeline.X] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY; + } + if (alpha == 1) { + bone.scaleX = x; + bone.scaleY = y; + } + else { + var bx = 0, by = 0; + if (setupPose) { + bx = bone.data.scaleX; + by = bone.data.scaleY; + } + else { + bx = bone.scaleX; + by = bone.scaleY; + } + if (mixingOut) { + x = Math.abs(x) * spine.MathUtils.signum(bx); + y = Math.abs(y) * spine.MathUtils.signum(by); + } + else { + bx = Math.abs(bx) * spine.MathUtils.signum(x); + by = Math.abs(by) * spine.MathUtils.signum(y); + } + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + } + }; + return ScaleTimeline; + }(TranslateTimeline)); + spine.ScaleTimeline = ScaleTimeline; + var ShearTimeline = (function (_super) { + __extends(ShearTimeline, _super); + function ShearTimeline(frameCount) { + _super.call(this, frameCount); + } + ShearTimeline.prototype.getPropertyId = function () { + return (TimelineType.shear << 24) + this.boneIndex; + }; + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + if (setupPose) { + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ShearTimeline.ENTRIES]) { + x = frames[frames.length + ShearTimeline.PREV_X]; + y = frames[frames.length + ShearTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES); + x = frames[frame + ShearTimeline.PREV_X]; + y = frames[frame + ShearTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime)); + x = x + (frames[frame + ShearTimeline.X] - x) * percent; + y = y + (frames[frame + ShearTimeline.Y] - y) * percent; + } + if (setupPose) { + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + } + else { + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + } + }; + return ShearTimeline; + }(TranslateTimeline)); + spine.ShearTimeline = ShearTimeline; + var ColorTimeline = (function (_super) { + __extends(ColorTimeline, _super); + function ColorTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + } + ColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.color << 24) + this.slotIndex; + }; + ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) { + frameIndex *= ColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + ColorTimeline.R] = r; + this.frames[frameIndex + ColorTimeline.G] = g; + this.frames[frameIndex + ColorTimeline.B] = b; + this.frames[frameIndex + ColorTimeline.A] = a; + }; + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + if (setupPose) + slot.color.setFromColor(slot.data.color); + return; + } + var r = 0, g = 0, b = 0, a = 0; + if (time >= frames[frames.length - ColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + ColorTimeline.PREV_R]; + g = frames[i + ColorTimeline.PREV_G]; + b = frames[i + ColorTimeline.PREV_B]; + a = frames[i + ColorTimeline.PREV_A]; + } + else { + var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES); + r = frames[frame + ColorTimeline.PREV_R]; + g = frames[frame + ColorTimeline.PREV_G]; + b = frames[frame + ColorTimeline.PREV_B]; + a = frames[frame + ColorTimeline.PREV_A]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + ColorTimeline.R] - r) * percent; + g += (frames[frame + ColorTimeline.G] - g) * percent; + b += (frames[frame + ColorTimeline.B] - b) * percent; + a += (frames[frame + ColorTimeline.A] - a) * percent; + } + if (alpha == 1) + slot.color.set(r, g, b, a); + else { + var color = slot.color; + if (setupPose) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + }; + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; + return ColorTimeline; + }(CurveTimeline)); + spine.ColorTimeline = ColorTimeline; + var AttachmentTimeline = (function () { + function AttachmentTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.attachmentNames = new Array(frameCount); + } + AttachmentTimeline.prototype.getPropertyId = function () { + return (TimelineType.attachment << 24) + this.slotIndex; + }; + AttachmentTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }; + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + var slot = skeleton.slots[this.slotIndex]; + if (mixingOut && setupPose) { + var attachmentName_1 = slot.data.attachmentName; + slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1)); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (setupPose) { + var attachmentName_2 = slot.data.attachmentName; + slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2)); + } + return; + } + var frameIndex = 0; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = Animation.binarySearch(frames, time, 1) - 1; + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex] + .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + return AttachmentTimeline; + }()); + spine.AttachmentTimeline = AttachmentTimeline; + var DeformTimeline = (function (_super) { + __extends(DeformTimeline, _super); + function DeformTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount); + this.frameVertices = new Array(frameCount); + } + DeformTimeline.prototype.getPropertyId = function () { + return (TimelineType.deform << 24) + this.slotIndex; + }; + DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { + this.frames[frameIndex] = time; + this.frameVertices[frameIndex] = vertices; + }; + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var slot = skeleton.slots[this.slotIndex]; + var slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) + return; + var frames = this.frames; + var verticesArray = slot.attachmentVertices; + if (time < frames[0]) { + if (setupPose) + spine.Utils.setArraySize(verticesArray, 0); + return; + } + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + if (verticesArray.length != vertexCount) + alpha = 1; + var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); + if (time >= frames[frames.length - 1]) { + var lastVertices = frameVertices[frames.length - 1]; + if (alpha == 1) { + spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); + } + else if (setupPose) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) { + var setup = setupVertices[i]; + vertices[i] = setup + (lastVertices[i] - setup) * alpha; + } + } + else { + for (var i = 0; i < vertexCount; i++) + vertices[i] = lastVertices[i] * alpha; + } + } + else { + for (var i = 0; i < vertexCount; i++) + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time); + var prevVertices = frameVertices[frame - 1]; + var nextVertices = frameVertices[frame]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + if (alpha == 1) { + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i]; + vertices[i] = prev + (nextVertices[i] - prev) * percent; + } + } + else if (setupPose) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i], setup = setupVertices[i]; + vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } + else { + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i]; + vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + else { + for (var i = 0; i < vertexCount; i++) { + var prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + } + }; + return DeformTimeline; + }(CurveTimeline)); + spine.DeformTimeline = DeformTimeline; + var EventTimeline = (function () { + function EventTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.events = new Array(frameCount); + } + EventTimeline.prototype.getPropertyId = function () { + return TimelineType.event << 24; + }; + EventTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + EventTimeline.prototype.setFrame = function (frameIndex, event) { + this.frames[frameIndex] = event.time; + this.events[frameIndex] = event; + }; + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + if (firedEvents == null) + return; + var frames = this.frames; + var frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, setupPose, mixingOut); + lastTime = -1; + } + else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + var frame = 0; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.binarySearch(frames, lastTime); + var frameTime = frames[frame]; + while (frame > 0) { + if (frames[frame - 1] != frameTime) + break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.push(this.events[frame]); + }; + return EventTimeline; + }()); + spine.EventTimeline = EventTimeline; + var DrawOrderTimeline = (function () { + function DrawOrderTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.drawOrders = new Array(frameCount); + } + DrawOrderTimeline.prototype.getPropertyId = function () { + return TimelineType.drawOrder << 24; + }; + DrawOrderTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) { + this.frames[frameIndex] = time; + this.drawOrders[frameIndex] = drawOrder; + }; + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var drawOrder = skeleton.drawOrder; + var slots = skeleton.slots; + if (mixingOut && setupPose) { + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (setupPose) + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frame = 0; + if (time >= frames[frames.length - 1]) + frame = frames.length - 1; + else + frame = Animation.binarySearch(frames, time) - 1; + var drawOrderToSetupIndex = this.drawOrders[frame]; + if (drawOrderToSetupIndex == null) + spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length); + else { + for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + }; + return DrawOrderTimeline; + }()); + spine.DrawOrderTimeline = DrawOrderTimeline; + var IkConstraintTimeline = (function (_super) { + __extends(IkConstraintTimeline, _super); + function IkConstraintTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + } + IkConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; + }; + IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection) { + frameIndex *= IkConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; + this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; + }; + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var frames = this.frames; + var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (time < frames[0]) { + if (setupPose) { + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + } + return; + } + if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { + if (setupPose) { + constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; + constraint.bendDirection = mixingOut ? constraint.data.bendDirection + : frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + else { + constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; + if (!mixingOut) + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + return; + } + var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES); + var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); + if (setupPose) { + constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; + constraint.bendDirection = mixingOut ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + else { + constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; + if (!mixingOut) + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + }; + IkConstraintTimeline.ENTRIES = 3; + IkConstraintTimeline.PREV_TIME = -3; + IkConstraintTimeline.PREV_MIX = -2; + IkConstraintTimeline.PREV_BEND_DIRECTION = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.BEND_DIRECTION = 2; + return IkConstraintTimeline; + }(CurveTimeline)); + spine.IkConstraintTimeline = IkConstraintTimeline; + var TransformConstraintTimeline = (function (_super) { + __extends(TransformConstraintTimeline, _super); + function TransformConstraintTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + } + TransformConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; + }; + TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) { + frameIndex *= TransformConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix; + this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; + this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; + }; + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var frames = this.frames; + var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (time < frames[0]) { + if (setupPose) { + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.rotateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + return; + } + var rotate = 0, translate = 0, scale = 0, shear = 0; + if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) { + var i = frames.length; + rotate = frames[i + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[i + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[i + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[i + TransformConstraintTimeline.PREV_SHEAR]; + } + else { + var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES); + rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[frame + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent; + scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; + shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; + } + if (setupPose) { + var data = constraint.data; + constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; + constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; + constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; + constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + constraint.scaleMix += (scale - constraint.scaleMix) * alpha; + constraint.shearMix += (shear - constraint.shearMix) * alpha; + } + }; + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; + return TransformConstraintTimeline; + }(CurveTimeline)); + spine.TransformConstraintTimeline = TransformConstraintTimeline; + var PathConstraintPositionTimeline = (function (_super) { + __extends(PathConstraintPositionTimeline, _super); + function PathConstraintPositionTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + } + PathConstraintPositionTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; + }; + PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) { + frameIndex *= PathConstraintPositionTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; + }; + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + if (setupPose) + constraint.position = constraint.data.position; + return; + } + var position = 0; + if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES]) + position = frames[frames.length + PathConstraintPositionTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES); + position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); + position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; + } + if (setupPose) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + }; + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; + return PathConstraintPositionTimeline; + }(CurveTimeline)); + spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; + var PathConstraintSpacingTimeline = (function (_super) { + __extends(PathConstraintSpacingTimeline, _super); + function PathConstraintSpacingTimeline(frameCount) { + _super.call(this, frameCount); + } + PathConstraintSpacingTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; + }; + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + if (setupPose) + constraint.spacing = constraint.data.spacing; + return; + } + var spacing = 0; + if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES]) + spacing = frames[frames.length + PathConstraintSpacingTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES); + spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); + spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; + } + if (setupPose) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + }; + return PathConstraintSpacingTimeline; + }(PathConstraintPositionTimeline)); + spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline; + var PathConstraintMixTimeline = (function (_super) { + __extends(PathConstraintMixTimeline, _super); + function PathConstraintMixTimeline(frameCount) { + _super.call(this, frameCount); + this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + } + PathConstraintMixTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; + }; + PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) { + frameIndex *= PathConstraintMixTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; + }; + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + if (setupPose) { + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + } + return; + } + var rotate = 0, translate = 0; + if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) { + rotate = frames[frames.length + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frames.length + PathConstraintMixTimeline.PREV_TRANSLATE]; + } + else { + var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES); + rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; + } + if (setupPose) { + constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; + constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + } + }; + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; + return PathConstraintMixTimeline; + }(CurveTimeline)); + spine.PathConstraintMixTimeline = PathConstraintMixTimeline; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationState = (function () { + function AnimationState(data) { + this.tracks = new Array(); + this.events = new Array(); + this.listeners = new Array(); + this.queue = new EventQueue(this); + this.propertyIDs = new spine.IntSet(); + this.animationsChanged = false; + this.timeScale = 1; + this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); + this.data = data; + } + AnimationState.prototype.update = function (delta) { + delta *= this.timeScale; + var tracks = this.tracks; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + var currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + var next = current.next; + if (next != null) { + var nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime = nextTime + delta * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom != null) { + next.mixTime += currentDelta; + next = next.mixingFrom; + } + continue; + } + } + else { + if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + } + this.updateMixingFrom(current, delta); + current.trackTime += currentDelta; + } + this.queue.drain(); + }; + AnimationState.prototype.updateMixingFrom = function (entry, delta) { + var from = entry.mixingFrom; + if (from == null) + return; + this.updateMixingFrom(from, delta); + if (entry.mixTime >= entry.mixDuration && from.mixingFrom != null && entry.mixTime > 0) { + entry.mixingFrom = null; + this.queue.end(from); + return; + } + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + from.trackTime += delta * from.timeScale; + entry.mixTime += delta * from.timeScale; + }; + AnimationState.prototype.apply = function (skeleton) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + var events = this.events; + var tracks = this.tracks; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null || current.delay > 0) + continue; + var mix = current.alpha; + if (current.mixingFrom != null) + mix *= this.applyMixingFrom(current, skeleton); + else if (current.trackTime >= current.trackEnd) + mix = 0; + var animationLast = current.animationLast, animationTime = current.getAnimationTime(); + var timelineCount = current.animation.timelines.length; + var timelines = current.animation.timelines; + if (mix == 1) { + for (var ii = 0; ii < timelineCount; ii++) + timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, true, false); + } + else { + var firstFrame = current.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = current.timelinesRotation; + var timelinesFirst = current.timelinesFirst; + for (var ii = 0; ii < timelineCount; ii++) { + var timeline = timelines[ii]; + if (timeline instanceof spine.RotateTimeline) { + this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelinesFirst[ii], timelinesRotation, ii << 1, firstFrame); + } + else + timeline.apply(skeleton, animationLast, animationTime, events, mix, timelinesFirst[ii], false); + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + this.queue.drain(); + }; + AnimationState.prototype.applyMixingFrom = function (entry, skeleton) { + var from = entry.mixingFrom; + if (from.mixingFrom != null) + this.applyMixingFrom(from, skeleton); + var mix = 0; + if (entry.mixDuration == 0) + mix = 1; + else { + mix = entry.mixTime / entry.mixDuration; + if (mix > 1) + mix = 1; + } + var events = mix < from.eventThreshold ? this.events : null; + var attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + var animationLast = from.animationLast, animationTime = from.getAnimationTime(); + var timelineCount = from.animation.timelines.length; + var timelines = from.animation.timelines; + var timelinesFirst = from.timelinesFirst; + var alpha = from.alpha * entry.mixAlpha * (1 - mix); + var firstFrame = from.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = from.timelinesRotation; + for (var i = 0; i < timelineCount; i++) { + var timeline = timelines[i]; + var setupPose = timelinesFirst[i]; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, setupPose, timelinesRotation, i << 1, firstFrame); + else { + if (!setupPose) { + if (!attachments && timeline instanceof spine.AttachmentTimeline) + continue; + if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) + continue; + } + timeline.apply(skeleton, animationLast, animationTime, events, alpha, setupPose, true); + } + } + if (entry.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + }; + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, setupPose, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, setupPose, false); + return; + } + var rotateTimeline = timeline; + var frames = rotateTimeline.frames; + var bone = skeleton.bones[rotateTimeline.boneIndex]; + if (time < frames[0]) { + if (setupPose) + bone.rotation = bone.data.rotation; + return; + } + var r2 = 0; + if (time >= frames[frames.length - spine.RotateTimeline.ENTRIES]) + r2 = bone.data.rotation + frames[frames.length + spine.RotateTimeline.PREV_ROTATION]; + else { + var frame = spine.Animation.binarySearch(frames, time, spine.RotateTimeline.ENTRIES); + var prevRotation = frames[frame + spine.RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + spine.RotateTimeline.PREV_TIME] - frameTime)); + r2 = frames[frame + spine.RotateTimeline.ROTATION] - prevRotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + r2 = prevRotation + r2 * percent + bone.data.rotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + } + var r1 = setupPose ? bone.data.rotation : bone.rotation; + var total = 0, diff = r2 - r1; + if (diff == 0) { + total = timelinesRotation[i]; + } + else { + diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360; + var lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } + else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + var current = diff > 0, dir = lastTotal >= 0; + if (spine.MathUtils.signum(lastDiff) != spine.MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * spine.MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * spine.MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360; + }; + AnimationState.prototype.queueEvents = function (entry, animationTime) { + var animationStart = entry.animationStart, animationEnd = entry.animationEnd; + var duration = animationEnd - animationStart; + var trackLastWrapped = entry.trackLast % duration; + var events = this.events; + var i = 0, n = events.length; + for (; i < n; i++) { + var event_1 = events[i]; + if (event_1.time < trackLastWrapped) + break; + if (event_1.time > animationEnd) + continue; + this.queue.event(entry, event_1); + } + if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) + : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { + this.queue.complete(entry); + } + for (; i < n; i++) { + var event_2 = events[i]; + if (event_2.time < animationStart) + continue; + this.queue.event(entry, events[i]); + } + }; + AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.clearTrack = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return; + var current = this.tracks[trackIndex]; + if (current == null) + return; + this.queue.end(current); + this.disposeNext(current); + var entry = current; + while (true) { + var from = entry.mixingFrom; + if (from == null) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + }; + AnimationState.prototype.setCurrent = function (index, current, interrupt) { + var from = this.expandToIndex(index); + this.tracks[index] = current; + if (from != null) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + current.mixTime = 0; + from.timelinesRotation.length = 0; + if (from.mixingFrom != null && from.mixDuration > 0) + current.mixAlpha *= Math.min(from.mixTime / from.mixDuration, 1); + } + this.queue.start(current); + }; + AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + }; + AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) { + if (animation == null) + throw new Error("animation cannot be null."); + var interrupt = true; + var current = this.expandToIndex(trackIndex); + if (current != null) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.disposeNext(current); + current = current.mixingFrom; + interrupt = false; + } + else + this.disposeNext(current); + } + var entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + }; + AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + }; + AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) { + if (animation == null) + throw new Error("animation cannot be null."); + var last = this.expandToIndex(trackIndex); + if (last != null) { + while (last.next != null) + last = last.next; + } + var entry = this.trackEntry(trackIndex, animation, loop, last); + if (last == null) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } + else { + last.next = entry; + if (delay <= 0) { + var duration = last.animationEnd - last.animationStart; + if (duration != 0) + delay += duration * (1 + ((last.trackTime / duration) | 0)) - this.data.getMix(last.animation, animation); + else + delay = 0; + } + } + entry.delay = delay; + return entry; + }; + AnimationState.prototype.setEmptyAnimation = function (trackIndex, mixDuration) { + var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.addEmptyAnimation = function (trackIndex, mixDuration, delay) { + if (delay <= 0) + delay -= mixDuration; + var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) { + var current = this.tracks[i]; + if (current != null) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.expandToIndex = function (index) { + if (index < this.tracks.length) + return this.tracks[index]; + spine.Utils.ensureArrayCapacity(this.tracks, index - this.tracks.length + 1, null); + this.tracks.length = index + 1; + return null; + }; + AnimationState.prototype.trackEntry = function (trackIndex, animation, loop, last) { + var entry = this.trackEntryPool.obtain(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixAlpha = 1; + entry.mixTime = 0; + entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); + return entry; + }; + AnimationState.prototype.disposeNext = function (entry) { + var next = entry.next; + while (next != null) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + }; + AnimationState.prototype._animationsChanged = function () { + this.animationsChanged = false; + var propertyIDs = this.propertyIDs; + var i = 0, n = this.tracks.length; + propertyIDs.clear(); + for (; i < n; i++) { + var entry = this.tracks[i]; + if (entry == null) + continue; + this.setTimelinesFirst(entry); + i++; + break; + } + for (; i < n; i++) { + var entry = this.tracks[i]; + if (entry != null) + this.checkTimelinesFirst(entry); + } + }; + AnimationState.prototype.setTimelinesFirst = function (entry) { + if (entry.mixingFrom != null) { + this.setTimelinesFirst(entry.mixingFrom); + this.checkTimelinesUsage(entry, entry.timelinesFirst); + return; + } + var propertyIDs = this.propertyIDs; + var timelines = entry.animation.timelines; + var n = timelines.length; + var usage = spine.Utils.setArraySize(entry.timelinesFirst, n, false); + for (var i = 0; i < n; i++) { + propertyIDs.add(timelines[i].getPropertyId()); + usage[i] = true; + } + }; + AnimationState.prototype.checkTimelinesFirst = function (entry) { + if (entry.mixingFrom != null) + this.checkTimelinesFirst(entry.mixingFrom); + this.checkTimelinesUsage(entry, entry.timelinesFirst); + }; + AnimationState.prototype.checkTimelinesUsage = function (entry, usageArray) { + var propertyIDs = this.propertyIDs; + var timelines = entry.animation.timelines; + var n = timelines.length; + var usage = spine.Utils.setArraySize(usageArray, n); + for (var i = 0; i < n; i++) + usage[i] = propertyIDs.add(timelines[i].getPropertyId()); + }; + AnimationState.prototype.getCurrent = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + }; + AnimationState.prototype.addListener = function (listener) { + if (listener == null) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + }; + AnimationState.prototype.removeListener = function (listener) { + var index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + }; + AnimationState.prototype.clearListeners = function () { + this.listeners.length = 0; + }; + AnimationState.prototype.clearListenerNotifications = function () { + this.queue.clear(); + }; + AnimationState.emptyAnimation = new spine.Animation("", [], 0); + return AnimationState; + }()); + spine.AnimationState = AnimationState; + var TrackEntry = (function () { + function TrackEntry() { + this.timelinesFirst = new Array(); + this.timelinesRotation = new Array(); + } + TrackEntry.prototype.reset = function () { + this.next = null; + this.mixingFrom = null; + this.animation = null; + this.listener = null; + this.timelinesFirst.length = 0; + this.timelinesRotation.length = 0; + }; + TrackEntry.prototype.getAnimationTime = function () { + if (this.loop) { + var duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return (this.trackTime % duration) + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + }; + TrackEntry.prototype.setAnimationLast = function (animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + }; + TrackEntry.prototype.isComplete = function () { + return this.trackTime >= this.animationEnd - this.animationStart; + }; + TrackEntry.prototype.resetRotationDirections = function () { + this.timelinesRotation.length = 0; + }; + return TrackEntry; + }()); + spine.TrackEntry = TrackEntry; + var EventQueue = (function () { + function EventQueue(animState) { + this.objects = []; + this.drainDisabled = false; + this.animState = animState; + } + EventQueue.prototype.start = function (entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.interrupt = function (entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + }; + EventQueue.prototype.end = function (entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.dispose = function (entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + }; + EventQueue.prototype.complete = function (entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + }; + EventQueue.prototype.event = function (entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + }; + EventQueue.prototype.drain = function () { + if (this.drainDisabled) + return; + this.drainDisabled = true; + var objects = this.objects; + var listeners = this.animState.listeners; + for (var i = 0; i < objects.length; i += 2) { + var type = objects[i]; + var entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener != null && entry.listener.start) + entry.listener.start(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].start) + listeners[ii].start(entry); + break; + case EventType.interrupt: + if (entry.listener != null && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].interrupt) + listeners[ii].interrupt(entry); + break; + case EventType.end: + if (entry.listener != null && entry.listener.end) + entry.listener.end(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].end) + listeners[ii].end(entry); + case EventType.dispose: + if (entry.listener != null && entry.listener.dispose) + entry.listener.dispose(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].dispose) + listeners[ii].dispose(entry); + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener != null && entry.listener.complete) + entry.listener.complete(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].complete) + listeners[ii].complete(entry); + break; + case EventType.event: + var event_3 = objects[i++ + 2]; + if (entry.listener != null && entry.listener.event) + entry.listener.event(entry, event_3); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].event) + listeners[ii].event(entry, event_3); + break; + } + } + this.clear(); + this.drainDisabled = false; + }; + EventQueue.prototype.clear = function () { + this.objects.length = 0; + }; + return EventQueue; + }()); + spine.EventQueue = EventQueue; + (function (EventType) { + EventType[EventType["start"] = 0] = "start"; + EventType[EventType["interrupt"] = 1] = "interrupt"; + EventType[EventType["end"] = 2] = "end"; + EventType[EventType["dispose"] = 3] = "dispose"; + EventType[EventType["complete"] = 4] = "complete"; + EventType[EventType["event"] = 5] = "event"; + })(spine.EventType || (spine.EventType = {})); + var EventType = spine.EventType; + var AnimationStateAdapter2 = (function () { + function AnimationStateAdapter2() { + } + AnimationStateAdapter2.prototype.start = function (entry) { + }; + AnimationStateAdapter2.prototype.interrupt = function (entry) { + }; + AnimationStateAdapter2.prototype.end = function (entry) { + }; + AnimationStateAdapter2.prototype.dispose = function (entry) { + }; + AnimationStateAdapter2.prototype.complete = function (entry) { + }; + AnimationStateAdapter2.prototype.event = function (entry, event) { + }; + return AnimationStateAdapter2; + }()); + spine.AnimationStateAdapter2 = AnimationStateAdapter2; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationStateData = (function () { + function AnimationStateData(skeletonData) { + this.animationToMixTime = {}; + this.defaultMix = 0; + if (skeletonData == null) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + AnimationStateData.prototype.setMix = function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (from == null) + throw new Error("Animation not found: " + fromName); + var to = this.skeletonData.findAnimation(toName); + if (to == null) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + }; + AnimationStateData.prototype.setMixWith = function (from, to, duration) { + if (from == null) + throw new Error("from cannot be null."); + if (to == null) + throw new Error("to cannot be null."); + var key = from.name + to.name; + this.animationToMixTime[key] = duration; + }; + AnimationStateData.prototype.getMix = function (from, to) { + var key = from.name + to.name; + var value = this.animationToMixTime[key]; + return value === undefined ? this.defaultMix : value; + }; + return AnimationStateData; + }()); + spine.AnimationStateData = AnimationStateData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AtlasAttachmentLoader = (function () { + function AtlasAttachmentLoader(atlas) { + this.atlas = atlas; + } + AtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.RegionAttachment(name); + attachment.setRegion(region); + return attachment; + }; + AtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.MeshAttachment(name); + attachment.region = region; + return attachment; + }; + AtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) { + return new spine.BoundingBoxAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { + return new spine.PathAttachment(name); + }; + return AtlasAttachmentLoader; + }()); + spine.AtlasAttachmentLoader = AtlasAttachmentLoader; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + _super.call(this, name); + this.worldVerticesLength = 0; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, worldVertices) { + this.computeWorldVerticesWith(slot, 0, this.worldVerticesLength, worldVertices, 0); + }; + VertexAttachment.prototype.computeWorldVerticesWith = function (slot, start, count, worldVertices, offset) { + count += offset; + var skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += 2) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += 2) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; + }; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + })(spine.AttachmentType || (spine.AttachmentType = {})); + var AttachmentType = spine.AttachmentType; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + _super.call(this, name); + this.color = new spine.Color(1, 1, 1, 1); + } + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + _super.call(this, name); + this.color = new spine.Color(1, 1, 1, 1); + this.inheritDeform = false; + this.tempColor = new spine.Color(0, 0, 0, 0); + } + MeshAttachment.prototype.updateUVs = function () { + var regionUVs = this.regionUVs; + var verticesLength = regionUVs.length; + var worldVerticesLength = (verticesLength >> 1) * 8; + if (this.worldVertices == null || this.worldVertices.length != worldVerticesLength) + this.worldVertices = spine.Utils.newFloatArray(worldVerticesLength); + var u = 0, v = 0, width = 0, height = 0; + if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; + } + if (this.region.rotate) { + for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { + this.worldVertices[w] = u + regionUVs[i + 1] * width; + this.worldVertices[w + 1] = v + height - regionUVs[i] * height; + } + } + else { + for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { + this.worldVertices[w] = u + regionUVs[i] * width; + this.worldVertices[w + 1] = v + regionUVs[i + 1] * height; + } + } + }; + MeshAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = this.color; + var alpha = skeletonColor.a * slotColor.a * meshColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier, skeletonColor.g * slotColor.g * meshColor.g * multiplier, skeletonColor.b * slotColor.b * meshColor.b * multiplier, alpha); + var deformArray = slot.attachmentVertices; + var vertices = this.vertices, worldVertices = this.worldVertices; + var bones = this.bones; + if (bones == null) { + var verticesLength = vertices.length; + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v = 0, w = 0; v < verticesLength; v += 2, w += 8) { + var vx = vertices[v], vy = vertices[v + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + return worldVertices; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = 0, v = 0, b = 0, n = bones.length; v < n; w += 8) { + var wx = 0, wy = 0; + var nn = bones[v++] + v; + for (; v < nn; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + } + else { + var deform = deformArray; + for (var w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 8) { + var wx = 0, wy = 0; + var nn = bones[v++] + v; + for (; v < nn; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + worldVertices[w + 2] = color.r; + worldVertices[w + 3] = color.g; + worldVertices[w + 4] = color.b; + worldVertices[w + 5] = color.a; + } + } + return worldVertices; + }; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + _super.call(this, name); + this.closed = false; + this.constantSpeed = false; + this.color = new spine.Color(1, 1, 1, 1); + } + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + _super.call(this, name); + this.x = 0; + this.y = 0; + this.scaleX = 1; + this.scaleY = 1; + this.rotation = 0; + this.width = 0; + this.height = 0; + this.color = new spine.Color(1, 1, 1, 1); + this.offset = spine.Utils.newFloatArray(8); + this.vertices = spine.Utils.newFloatArray(8 * 4); + this.tempColor = new spine.Color(1, 1, 1, 1); + } + RegionAttachment.prototype.setRegion = function (region) { + var vertices = this.vertices; + if (region.rotate) { + vertices[RegionAttachment.U2] = region.u; + vertices[RegionAttachment.V2] = region.v2; + vertices[RegionAttachment.U3] = region.u; + vertices[RegionAttachment.V3] = region.v; + vertices[RegionAttachment.U4] = region.u2; + vertices[RegionAttachment.V4] = region.v; + vertices[RegionAttachment.U1] = region.u2; + vertices[RegionAttachment.V1] = region.v2; + } + else { + vertices[RegionAttachment.U1] = region.u; + vertices[RegionAttachment.V1] = region.v2; + vertices[RegionAttachment.U2] = region.u; + vertices[RegionAttachment.V2] = region.v; + vertices[RegionAttachment.U3] = region.u2; + vertices[RegionAttachment.V3] = region.v; + vertices[RegionAttachment.U4] = region.u2; + vertices[RegionAttachment.V4] = region.v2; + } + this.region = region; + }; + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = this.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var 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); + var vertices = this.vertices; + var offset = this.offset; + var bone = slot.bone; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = offset[RegionAttachment.OX1]; + offsetY = offset[RegionAttachment.OY1]; + vertices[RegionAttachment.X1] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y1] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + offsetX = offset[RegionAttachment.OX2]; + offsetY = offset[RegionAttachment.OY2]; + vertices[RegionAttachment.X2] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y2] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + offsetX = offset[RegionAttachment.OX3]; + offsetY = offset[RegionAttachment.OY3]; + vertices[RegionAttachment.X3] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y3] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + offsetX = offset[RegionAttachment.OX4]; + offsetY = offset[RegionAttachment.OY4]; + vertices[RegionAttachment.X4] = offsetX * a + offsetY * b + x; + vertices[RegionAttachment.Y4] = offsetX * c + offsetY * d + y; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + return vertices; + }; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(spine.BlendMode || (spine.BlendMode = {})); + var BlendMode = spine.BlendMode; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + var skeleton = this.skeleton; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (skeleton.flipY) { + y = -y; + lc = -lc; + ld = -ld; + } + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + this.worldX = x + skeleton.x; + this.worldY = y + skeleton.y; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case spine.TransformMode.Normal: { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case spine.TransformMode.OnlyTranslation: { + var rotationY = rotation + 90 + shearY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case spine.TransformMode.NoRotationOrReflection: { + var s = pa * pa + pc * pc; + var prx = 0; + if (s > 0.0001) { + s = Math.abs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; + } + else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; + } + var rx = rotation + shearX - prx; + var ry = rotation + shearY - prx + 90; + var la = spine.MathUtils.cosDeg(rx) * scaleX; + var lb = spine.MathUtils.cosDeg(ry) * scaleY; + var lc = spine.MathUtils.sinDeg(rx) * scaleX; + var ld = spine.MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: { + var cos = spine.MathUtils.cosDeg(rotation); + var sin = spine.MathUtils.sinDeg(rotation); + var za = pa * cos + pb * sin; + var zc = pc * cos + pd * sin; + var s = Math.sqrt(za * za + zc * zc); + if (s > 0.00001) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + var r = Math.PI / 2 + Math.atan2(zc, za); + var zb = Math.cos(r) * s; + var zd = Math.sin(r) * s; + var la = spine.MathUtils.cosDeg(shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; + var lc = spine.MathUtils.sinDeg(shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { + this.b = -this.b; + this.d = -this.d; + } + return; + } + } + if (this.skeleton.flipX) { + this.a = -this.a; + this.b = -this.b; + } + if (this.skeleton.flipY) { + this.c = -this.c; + this.d = -this.d; + } + }; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + }; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.c * this.c); + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.b * this.b + this.d * this.d); + }; + Bone.prototype.worldToLocalRotationX = function () { + var parent = this.parent; + if (parent == null) + return this.arotation; + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; + return Math.atan2(pa * c - pc * a, pd * a - pb * c) * spine.MathUtils.radDeg; + }; + Bone.prototype.worldToLocalRotationY = function () { + var parent = this.parent; + if (parent == null) + return this.arotation; + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; + return Math.atan2(pa * d - pc * b, pd * b - pb * d) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; + Bone.prototype.updateAppliedTransform = function () { + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + this.ax = this.worldX; + this.ay = this.worldY; + this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = (dx * pd * pid - dy * pb * pid); + this.ay = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + } + else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; + } + }; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; + }; + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + }; + return Bone; + }()); + spine.Bone = Bone; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoneData = (function () { + function BoneData(index, name, parent) { + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + return BoneData; + }()); + spine.BoneData = BoneData; + (function (TransformMode) { + TransformMode[TransformMode["Normal"] = 0] = "Normal"; + TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; + TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(spine.TransformMode || (spine.TransformMode = {})); + var TransformMode = spine.TransformMode; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; +})(spine || (spine = {})); +var spine; +(function (spine) { + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.mix = 1; + this.bendDirection = 0; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.bendDirection = data.bendDirection; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + IkConstraint.prototype.getOrder = function () { + return this.data.order; + }; + IkConstraint.prototype.apply = function () { + this.update(); + }; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); + break; + } + }; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) { + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var p = bone.parent; + var id = 1 / (p.a * p.d - p.b * p.c); + var x = targetX - p.worldX, y = targetY - p.worldY; + var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; + var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); + }; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + if (!parent.appliedValid) + parent.updateAppliedTransform(); + if (!child.appliedValid) + child.updateAppliedTransform(); + var px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } + else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } + else + os2 = 0; + var cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + var u = Math.abs(psx - psy) <= 0.0001; + if (!u) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } + else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + var pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + var id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; + var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + x = cwx - pp.worldX; + y = cwy - pp.worldY; + var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1 = 0, a2 = 0; + outer: if (u) { + l2 *= psx; + var cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + cos = -1; + else if (cos > 1) + cos = 1; + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } + else { + a = psx * l2; + b = psy * l2; + var aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + var c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + var q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) / 2; + var r0 = q / c2, r1 = c / q; + var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + var minAngle = 0, minDist = Number.MAX_VALUE, minX = 0, minY = 0; + var maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; + x = l1 + a; + d = x * x; + if (d > maxDist) { + maxAngle = 0; + maxDist = d; + maxX = x; + } + x = l1 - a; + d = x * x; + if (d < minDist) { + minAngle = spine.MathUtils.PI; + minDist = d; + minX = x; + } + var angle = Math.acos(-a * l1 / (aa - bb)); + x = a * Math.cos(angle) + l1; + y = b * Math.sin(angle); + d = x * x + y * y; + if (d < minDist) { + minAngle = angle; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = angle; + maxDist = d; + maxX = x; + maxY = y; + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + var os = Math.atan2(cy, cx) * s2; + var rotation = parent.arotation; + a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * spine.MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + }; + return IkConstraint; + }()); + spine.IkConstraint = IkConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraintData = (function () { + function IkConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.bendDirection = 1; + this.mix = 1; + this.name = name; + } + return IkConstraintData; + }()); + spine.IkConstraintData = IkConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraint = (function () { + function PathConstraint(data, skeleton) { + this.position = 0; + this.spacing = 0; + this.rotateMix = 0; + this.translateMix = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + } + PathConstraint.prototype.apply = function () { + this.update(); + }; + PathConstraint.prototype.update = function () { + var attachment = this.target.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + return; + var rotateMix = this.rotateMix, translateMix = this.translateMix; + var translate = translateMix > 0, rotate = rotateMix > 0; + if (!translate && !rotate) + return; + var data = this.data; + var spacingMode = data.spacingMode; + var lengthSpacing = spacingMode == spine.SpacingMode.Length; + var rotateMode = data.rotateMode; + var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale; + var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + var bones = this.bones; + var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null; + var spacing = this.spacing; + if (scale || lengthSpacing) { + if (scale) + lengths = spine.Utils.setArraySize(this.lengths, boneCount); + for (var i = 0, n = spacesCount - 1; i < n;) { + var bone = bones[i]; + var length_1 = bone.data.length, x = length_1 * bone.a, y = length_1 * bone.c; + length_1 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_1; + spaces[++i] = lengthSpacing ? Math.max(0, length_1 + spacing) : spacing; + } + } + else { + for (var i = 1; i < spacesCount; i++) + spaces[i] = spacing; + } + var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, spacingMode == spine.SpacingMode.Percent); + var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + var tip = false; + if (offsetRotation == 0) + tip = rotateMode == spine.RotateMode.Chain; + else { + tip = false; + var p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + } + for (var i = 0, p = 3; i < boneCount; i++, p += 3) { + var bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; + var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + var length_2 = lengths[i]; + if (length_2 != 0) { + var s = (Math.sqrt(dx * dx + dy * dy) / length_2 - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (rotate) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + var length_3 = bone.data.length; + boneX += (length_3 * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length_3 * (sin * a + cos * c) - dy) * rotateMix; + } + else { + r += offsetRotation; + } + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.appliedValid = false; + } + }; + PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) { + var target = this.target; + var position = this.position; + var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + var closed = path.closed; + var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; + if (!path.constantSpeed) { + var lengths = path.lengths; + curveCount -= closed ? 1 : 2; + var pathLength_1 = lengths[curveCount]; + if (percentPosition) + position *= pathLength_1; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength_1; + } + world = spine.Utils.setArraySize(this.world, 8); + for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength_1; + if (p < 0) + p += pathLength_1; + curve = 0; + } + else if (p < 0) { + if (prevCurve != PathConstraint.BEFORE) { + prevCurve = PathConstraint.BEFORE; + path.computeWorldVerticesWith(target, 2, 4, world, 0); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength_1) { + if (prevCurve != PathConstraint.AFTER) { + prevCurve = PathConstraint.AFTER; + path.computeWorldVerticesWith(target, verticesLength - 6, 4, world, 0); + } + this.addAfterPosition(p - pathLength_1, world, 0, out, o); + continue; + } + for (;; curve++) { + var length_4 = lengths[curve]; + if (p > length_4) + continue; + if (curve == 0) + p /= length_4; + else { + var prev = lengths[curve - 1]; + p = (p - prev) / (length_4 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVerticesWith(target, verticesLength - 4, 4, world, 0); + path.computeWorldVerticesWith(target, 0, 4, world, 4); + } + else + path.computeWorldVerticesWith(target, curve * 6 + 2, 8, world, 0); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); + } + return out; + } + if (closed) { + verticesLength += 2; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVerticesWith(target, 2, verticesLength - 4, world, 0); + path.computeWorldVerticesWith(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else { + curveCount--; + verticesLength -= 4; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVerticesWith(target, 2, verticesLength, world, 0); + } + var curves = spine.Utils.setArraySize(this.curves, curveCount); + var pathLength = 0; + var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (var i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (percentPosition) + position *= pathLength; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength; + } + var segments = this.segments; + var curveLength = 0; + for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } + else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (;; curve++) { + var length_5 = curves[curve]; + if (p > length_5) + continue; + if (curve == 0) + p /= length_5; + else { + var prev = curves[curve - 1]; + p = (p - prev) / (length_5 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + var ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (;; segment++) { + var length_6 = segments[segment]; + if (p > length_6) + continue; + if (segment == 0) + p /= length_6; + else { + var prev = segments[segment - 1]; + p = segment + (p - prev) / (length_6 - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + } + return out; + }; + PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) { + var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) { + var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) + p = 0.0001; + var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + }; + PathConstraint.prototype.getOrder = function () { + return this.data.order; + }; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + return PathConstraint; + }()); + spine.PathConstraint = PathConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraintData = (function () { + function PathConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.name = name; + } + return PathConstraintData; + }()); + spine.PathConstraintData = PathConstraintData; + (function (PositionMode) { + PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; + PositionMode[PositionMode["Percent"] = 1] = "Percent"; + })(spine.PositionMode || (spine.PositionMode = {})); + var PositionMode = spine.PositionMode; + (function (SpacingMode) { + SpacingMode[SpacingMode["Length"] = 0] = "Length"; + SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; + SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; + })(spine.SpacingMode || (spine.SpacingMode = {})); + var SpacingMode = spine.SpacingMode; + (function (RotateMode) { + RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; + RotateMode[RotateMode["Chain"] = 1] = "Chain"; + RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; + })(spine.RotateMode || (spine.RotateMode = {})); + var RotateMode = spine.RotateMode; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Assets = (function () { + function Assets(clientId) { + this.toLoad = new Array(); + this.assets = {}; + this.clientId = clientId; + } + Assets.prototype.loaded = function () { + var i = 0; + for (var v in this.assets) + i++; + return i; + }; + return Assets; + }()); + var SharedAssetManager = (function () { + function SharedAssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.clientAssets = {}; + this.queuedAssets = {}; + this.rawAssets = {}; + this.errors = {}; + this.pathPrefix = pathPrefix; + } + SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) { + clientAssets = new Assets(clientId); + this.clientAssets[clientId] = clientAssets; + } + if (textureLoader !== null) + clientAssets.textureLoader = textureLoader; + clientAssets.toLoad.push(path); + if (this.queuedAssets[path] === path) { + return false; + } + else { + this.queuedAssets[path] = path; + return true; + } + }; + SharedAssetManager.prototype.loadText = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = request.responseText; + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadJson = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = JSON.parse(request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, textureLoader, path)) + return; + var img = new Image(); + img.src = path; + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + _this.rawAssets[path] = img; + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + }; + }; + SharedAssetManager.prototype.get = function (clientId, path) { + path = this.pathPrefix + path; + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + return clientAssets.assets[path]; + }; + SharedAssetManager.prototype.updateClientAssets = function (clientAssets) { + for (var i = 0; i < clientAssets.toLoad.length; i++) { + var path = clientAssets.toLoad[i]; + var asset = clientAssets.assets[path]; + if (asset === null || asset === undefined) { + var rawAsset = this.rawAssets[path]; + if (rawAsset === null || rawAsset === undefined) + continue; + if (rawAsset instanceof HTMLImageElement) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + } + }; + SharedAssetManager.prototype.isLoadingComplete = function (clientId) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + this.updateClientAssets(clientAssets); + return clientAssets.toLoad.length == clientAssets.loaded(); + }; + SharedAssetManager.prototype.dispose = function () { + }; + SharedAssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + SharedAssetManager.prototype.getErrors = function () { + return this.errors; + }; + return SharedAssetManager; + }()); + spine.SharedAssetManager = SharedAssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skeleton = (function () { + function Skeleton(data) { + this._updateCache = new Array(); + this.updateCacheReset = new Array(); + this.time = 0; + this.flipX = false; + this.flipY = false; + this.x = 0; + this.y = 0; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) { + var boneData = data.bones[i]; + var bone = void 0; + if (boneData.parent == null) + bone = new spine.Bone(boneData, this, null); + else { + var parent_1 = this.bones[boneData.parent.index]; + bone = new spine.Bone(boneData, this, parent_1); + parent_1.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (var i = 0; i < data.slots.length; i++) { + var slotData = data.slots[i]; + var bone = this.bones[slotData.boneData.index]; + var slot = new spine.Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (var i = 0; i < data.ikConstraints.length; i++) { + var ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (var i = 0; i < data.transformConstraints.length; i++) { + var transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (var i = 0; i < data.pathConstraints.length; i++) { + var pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this)); + } + this.color = new spine.Color(1, 1, 1, 1); + this.updateCache(); + } + Skeleton.prototype.updateCache = function () { + var updateCache = this._updateCache; + updateCache.length = 0; + this.updateCacheReset.length = 0; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].sorted = false; + var ikConstraints = this.ikConstraints; + var transformConstraints = this.transformConstraints; + var pathConstraints = this.pathConstraints; + var ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + var constraintCount = ikCount + transformCount + pathCount; + outer: for (var i = 0; i < constraintCount; i++) { + for (var ii = 0; ii < ikCount; ii++) { + var constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < transformCount; ii++) { + var constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < pathCount; ii++) { + var constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (var i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + }; + Skeleton.prototype.sortIkConstraint = function (constraint) { + var target = constraint.target; + this.sortBone(target); + var constrained = constraint.bones; + var parent = constrained[0]; + this.sortBone(parent); + if (constrained.length > 1) { + var child = constrained[constrained.length - 1]; + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + this._updateCache.push(constraint); + this.sortReset(parent.children); + constrained[constrained.length - 1].sorted = true; + }; + Skeleton.prototype.sortPathConstraint = function (constraint) { + var slot = constraint.target; + var slotIndex = slot.data.index; + var slotBone = slot.bone; + if (this.skin != null) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (var ii = 0, nn = this.data.skins.length; ii < nn; ii++) + this.sortPathConstraintAttachment(this.data.skins[ii], slotIndex, slotBone); + var attachment = slot.getAttachment(); + if (attachment instanceof spine.PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var ii = 0; ii < boneCount; ii++) + this.sortBone(constrained[ii]); + this._updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + }; + Skeleton.prototype.sortTransformConstraint = function (constraint) { + this.sortBone(constraint.target); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var ii = 0; ii < boneCount; ii++) + this.sortBone(constrained[ii]); + this._updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + }; + Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) { + var attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (var key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + }; + Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) { + if (!(attachment instanceof spine.PathAttachment)) + return; + var pathBones = attachment.bones; + if (pathBones == null) + this.sortBone(slotBone); + else { + var bones = this.bones; + var i = 0; + while (i < pathBones.length) { + var boneCount = pathBones[i++]; + for (var n = i + boneCount; i < n; i++) { + var boneIndex = pathBones[i]; + this.sortBone(bones[boneIndex]); + } + } + } + }; + Skeleton.prototype.sortBone = function (bone) { + if (bone.sorted) + return; + var parent = bone.parent; + if (parent != null) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + }; + Skeleton.prototype.sortReset = function (bones) { + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + }; + Skeleton.prototype.updateWorldTransform = function () { + var updateCacheReset = this.updateCacheReset; + for (var i = 0, n = updateCacheReset.length; i < n; i++) { + var bone = updateCacheReset[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + var updateCache = this._updateCache; + for (var i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + }; + Skeleton.prototype.setToSetupPose = function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }; + Skeleton.prototype.setBonesToSetupPose = function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + constraint.bendDirection = constraint.data.bendDirection; + constraint.mix = constraint.data.mix; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + } + }; + Skeleton.prototype.setSlotsToSetupPose = function () { + var slots = this.slots; + spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + }; + Skeleton.prototype.getRootBone = function () { + if (this.bones.length == 0) + return null; + return this.bones[0]; + }; + Skeleton.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + }; + Skeleton.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) + return i; + return -1; + }; + Skeleton.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + }; + Skeleton.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) + return i; + return -1; + }; + Skeleton.prototype.setSkinByName = function (skinName) { + var skin = this.data.findSkin(skinName); + if (skin == null) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + }; + Skeleton.prototype.setSkin = function (newSkin) { + if (newSkin != null) { + if (this.skin != null) + newSkin.attachAll(this, this.skin); + else { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var name_1 = slot.data.attachmentName; + if (name_1 != null) { + var attachment = newSkin.getAttachment(i, name_1); + if (attachment != null) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + }; + Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) { + return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName); + }; + Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) { + if (attachmentName == null) + throw new Error("attachmentName cannot be null."); + if (this.skin != null) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + return attachment; + } + if (this.data.defaultSkin != null) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }; + Skeleton.prototype.setAttachment = function (slotName, attachmentName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName != null) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + }; + Skeleton.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + }; + Skeleton.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.getBounds = function (offset, size) { + if (offset == null) + throw new Error("offset cannot be null."); + if (size == null) + throw new Error("size cannot be null."); + var drawOrder = this.drawOrder; + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var vertices = null; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) + vertices = attachment.updateWorldVertices(slot, false); + else if (attachment instanceof spine.MeshAttachment) + vertices = attachment.updateWorldVertices(slot, true); + if (vertices != null) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 8) { + var x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + }; + Skeleton.prototype.update = function (delta) { + this.time += delta; + }; + return Skeleton; + }()); + spine.Skeleton = Skeleton; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBounds = (function () { + function SkeletonBounds() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new spine.Pool(function () { + return spine.Utils.newFloatArray(16); + }); + } + SkeletonBounds.prototype.update = function (skeleton, updateAabb) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + var boundingBoxes = this.boundingBoxes; + var polygons = this.polygons; + var polygonPool = this.polygonPool; + var slots = skeleton.slots; + var slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (var i = 0; i < slotCount; i++) { + var slot = slots[i]; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.BoundingBoxAttachment) { + var boundingBox = attachment; + boundingBoxes.push(boundingBox); + var polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, polygon); + } + } + if (updateAabb) { + this.aabbCompute(); + } + else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + }; + SkeletonBounds.prototype.aabbCompute = function () { + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + var vertices = polygon; + for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) { + var x = vertices[ii]; + var y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + }; + SkeletonBounds.prototype.aabbContainsPoint = function (x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + }; + SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) { + var minX = this.minX; + var minY = this.minY; + var maxX = this.maxX; + var maxY = this.maxY; + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + return false; + var m = (y2 - y1) / (x2 - x1); + var y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + var x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + }; + SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + }; + SkeletonBounds.prototype.containsPoint = function (x, y) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) { + var vertices = polygon; + var nn = polygon.length; + var prevIndex = nn - 2; + var inside = false; + for (var ii = 0; ii < nn; ii += 2) { + var vertexY = vertices[ii + 1]; + var prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + var vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + }; + SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) { + var vertices = polygon; + var nn = polygon.length; + var width12 = x1 - x2, height12 = y1 - y2; + var det1 = x1 * y2 - y1 * x2; + var x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (var ii = 0; ii < nn; ii += 2) { + var x4 = vertices[ii], y4 = vertices[ii + 1]; + var det2 = x3 * y4 - y3 * x4; + var width34 = x3 - x4, height34 = y3 - y4; + var det3 = width12 * height34 - height12 * width34; + var x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + var y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + }; + SkeletonBounds.prototype.getPolygon = function (boundingBox) { + if (boundingBox == null) + throw new Error("boundingBox cannot be null."); + var index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + }; + SkeletonBounds.prototype.getWidth = function () { + return this.maxX - this.minX; + }; + SkeletonBounds.prototype.getHeight = function () { + return this.maxY - this.minY; + }; + return SkeletonBounds; + }()); + spine.SkeletonBounds = SkeletonBounds; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonData = (function () { + function SkeletonData() { + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + this.fps = 0; + } + SkeletonData.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + }; + SkeletonData.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) + return i; + return -1; + }; + SkeletonData.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + }; + SkeletonData.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) + return i; + return -1; + }; + SkeletonData.prototype.findSkin = function (skinName) { + if (skinName == null) + throw new Error("skinName cannot be null."); + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) { + var skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + }; + SkeletonData.prototype.findEvent = function (eventDataName) { + if (eventDataName == null) + throw new Error("eventDataName cannot be null."); + var events = this.events; + for (var i = 0, n = events.length; i < n; i++) { + var event_4 = events[i]; + if (event_4.name == eventDataName) + return event_4; + } + return null; + }; + SkeletonData.prototype.findAnimation = function (animationName) { + if (animationName == null) + throw new Error("animationName cannot be null."); + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) { + var animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + }; + SkeletonData.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) { + if (pathConstraintName == null) + throw new Error("pathConstraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) + if (pathConstraints[i].name == pathConstraintName) + return i; + return -1; + }; + return SkeletonData; + }()); + spine.SkeletonData = SkeletonData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonJson = (function () { + function SkeletonJson(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonJson.prototype.readSkeletonData = function (json) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + var root = typeof (json) === "string" ? JSON.parse(json) : json; + var skeletonMap = root.skeleton; + if (skeletonMap != null) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (var i = 0; i < root.bones.length; i++) { + var boneMap = root.bones[i]; + var parent_2 = null; + var parentName = this.getValue(boneMap, "parent", null); + if (parentName != null) { + parent_2 = skeletonData.findBone(parentName); + if (parent_2 == null) + throw new Error("Parent bone not found: " + parentName); + } + var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_2); + data.length = this.getValue(boneMap, "length", 0) * scale; + data.x = this.getValue(boneMap, "x", 0) * scale; + data.y = this.getValue(boneMap, "y", 0) * scale; + data.rotation = this.getValue(boneMap, "rotation", 0); + data.scaleX = this.getValue(boneMap, "scaleX", 1); + data.scaleY = this.getValue(boneMap, "scaleY", 1); + data.shearX = this.getValue(boneMap, "shearX", 0); + data.shearY = this.getValue(boneMap, "shearY", 0); + data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, "transform", "normal")); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (var i = 0; i < root.slots.length; i++) { + var slotMap = root.slots[i]; + var slotName = slotMap.name; + var boneName = slotMap.bone; + var boneData = skeletonData.findBone(boneName); + if (boneData == null) + throw new Error("Slot bone not found: " + boneName); + var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData); + var color = this.getValue(slotMap, "color", null); + if (color != null) + data.color.setFromString(color); + data.attachmentName = this.getValue(slotMap, "attachment", null); + data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (var i = 0; i < root.ik.length; i++) { + var constraintMap = root.ik[i]; + var data = new spine.IkConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("IK bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("IK target bone not found: " + targetName); + data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.mix = this.getValue(constraintMap, "mix", 1); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (var i = 0; i < root.transform.length; i++) { + var constraintMap = root.transform[i]; + var data = new spine.TransformConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("Transform constraint target bone not found: " + targetName); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.offsetX = this.getValue(constraintMap, "x", 0) * scale; + data.offsetY = this.getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0); + data.offsetShearY = this.getValue(constraintMap, "shearY", 0); + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + data.scaleMix = this.getValue(constraintMap, "scaleMix", 1); + data.shearMix = this.getValue(constraintMap, "shearMix", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (var i = 0; i < root.path.length; i++) { + var constraintMap = root.path[i]; + var data = new spine.PathConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + if (data.target == null) + throw new Error("Path target slot not found: " + targetName); + data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent")); + data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length")); + data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent")); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.position = this.getValue(constraintMap, "position", 0); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = this.getValue(constraintMap, "spacing", 0); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (var skinName in root.skins) { + var skinMap = root.skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + var slotMap = skinMap[slotName]; + for (var entryName in slotMap) { + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); + if (attachment != null) + skin.addAttachment(slotIndex, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (var i = 0, n = this.linkedMeshes.length; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_3 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_3 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.setParentMesh(parent_3); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (var eventName in root.events) { + var eventMap = root.events[eventName]; + var data = new spine.EventData(eventName); + data.intValue = this.getValue(eventMap, "int", 0); + data.floatValue = this.getValue(eventMap, "float", 0); + data.stringValue = this.getValue(eventMap, "string", ""); + skeletonData.events.push(data); + } + } + if (root.animations) { + for (var animationName in root.animations) { + var animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + }; + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { + var scale = this.scale; + name = this.getValue(map, "name", name); + var type = this.getValue(map, "type", "region"); + switch (type) { + case "region": { + var path = this.getValue(map, "path", name); + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = this.getValue(map, "x", 0) * scale; + region.y = this.getValue(map, "y", 0) * scale; + region.scaleX = this.getValue(map, "scaleX", 1); + region.scaleY = this.getValue(map, "scaleY", 1); + region.rotation = this.getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + var color = this.getValue(map, "color", null); + if (color != null) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + this.readVertices(map, box, map.vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + var path = this.getValue(map, "path", name); + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + var color = this.getValue(map, "color", null); + if (color != null) + mesh.color.setFromString(color); + var parent_4 = this.getValue(map, "parent", null); + if (parent_4 != null) { + mesh.inheritDeform = this.getValue(map, "deform", true); + this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_4)); + return mesh; + } + var uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = this.getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = this.getValue(map, "closed", false); + path.constantSpeed = this.getValue(map, "constantSpeed", true); + var vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + var color = this.getValue(map, "color", null); + if (color != null) + path.color.setFromString(color); + return path; + } + } + return null; + }; + SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) { + var scale = this.scale; + attachment.worldVerticesLength = verticesLength; + var vertices = map.vertices; + if (verticesLength == vertices.length) { + if (scale != 1) { + for (var i = 0, n = vertices.length; i < n; i++) + vertices[i] *= scale; + } + attachment.vertices = spine.Utils.toFloatArray(vertices); + return; + } + var weights = new Array(); + var bones = new Array(); + for (var i = 0, n = vertices.length; i < n;) { + var boneCount = vertices[i++]; + bones.push(boneCount); + for (var nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = spine.Utils.toFloatArray(weights); + }; + SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) { + var scale = this.scale; + var timelines = new Array(); + var duration = 0; + if (map.slots) { + for (var slotName in map.slots) { + var slotMap = map.slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + if (timelineName == "color") { + var timeline = new spine.ColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var color = new spine.Color(); + color.setFromString(valueMap.color); + timeline.setFrame(frameIndex, valueMap.time, color.r, color.g, color.b, color.a); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); + } + else if (timelineName = "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else + throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + if (map.bones) { + for (var boneName in map.bones) { + var boneMap = map.bones[boneName]; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) + throw new Error("Bone not found: " + boneName); + for (var timelineName in boneMap) { + var timelineMap = boneMap[timelineName]; + if (timelineName === "rotate") { + var timeline = new spine.RotateTimeline(timelineMap.length); + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, valueMap.angle); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]); + } + else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "scale") + timeline = new spine.ScaleTimeline(timelineMap.length); + else if (timelineName === "shear") + timeline = new spine.ShearTimeline(timelineMap.length); + else { + timeline = new spine.TranslateTimeline(timelineMap.length); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var x = this.getValue(valueMap, "x", 0), y = this.getValue(valueMap, "y", 0); + timeline.setFrame(frameIndex, valueMap.time, x * timelineScale, y * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); + } + } + } + if (map.ik) { + for (var constraintName in map.ik) { + var constraintMap = map.ik[constraintName]; + var constraint = skeletonData.findIkConstraint(constraintName); + var timeline = new spine.IkConstraintTimeline(constraintMap.length); + timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + } + if (map.transform) { + for (var constraintName in map.transform) { + var constraintMap = map.transform[constraintName]; + var constraint = skeletonData.findTransformConstraint(constraintName); + var timeline = new spine.TransformConstraintTimeline(constraintMap.length); + timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + } + if (map.paths) { + for (var constraintName in map.paths) { + var constraintMap = map.paths[constraintName]; + var index = skeletonData.findPathConstraintIndex(constraintName); + if (index == -1) + throw new Error("Path constraint not found: " + constraintName); + var data = skeletonData.pathConstraints[index]; + for (var timelineName in constraintMap) { + var timelineMap = constraintMap[timelineName]; + if (timelineName === "position" || timelineName === "spacing") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "spacing") { + timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(timelineMap.length); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, timelineName, 0) * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + } + else if (timelineName === "mix") { + var timeline = new spine.PathConstraintMixTimeline(timelineMap.length); + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + } + } + } + } + if (map.deform) { + for (var deformName in map.deform) { + var deformMap = map.deform[deformName]; + var skin = skeletonData.findSkin(deformName); + if (skin == null) + throw new Error("Skin not found: " + deformName); + for (var slotName in deformMap) { + var slotMap = deformMap[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotMap.name); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + var attachment = skin.getAttachment(slotIndex, timelineName); + if (attachment == null) + throw new Error("Deform attachment not found: " + timelineMap.name); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var timeline = new spine.DeformTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + var frameIndex = 0; + for (var j = 0; j < timelineMap.length; j++) { + var valueMap = timelineMap[j]; + var deform = void 0; + var verticesValue = this.getValue(valueMap, "vertices", null); + if (verticesValue == null) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = this.getValue(valueMap, "offset", 0); + spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (var i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (var i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frameIndex, valueMap.time, deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_5 = new spine.Event(eventMap.time, eventData); + event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + timeline.setFrame(frameIndex++, event_5); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.curve) + return; + if (map.curve === "stepped") + timeline.setStepped(frameIndex); + else if (Object.prototype.toString.call(map.curve) === '[object Array]') { + var curve = map.curve; + timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + SkeletonJson.transformModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.TransformMode.Normal; + if (str == "onlytranslation") + return spine.TransformMode.OnlyTranslation; + if (str == "norotationorreflection") + return spine.TransformMode.NoRotationOrReflection; + if (str == "noscale") + return spine.TransformMode.NoScale; + if (str == "noscaleorreflection") + return spine.TransformMode.NoScaleOrReflection; + throw new Error("Unknown transform mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.addAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.attachmentVertices = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.attachmentVertices.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + region.rotate = reader.readValue() == "true"; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + _super.apply(this, arguments); + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect; + var offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; + bone.a *= s; + bone.c *= s; + s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.getOrder = function () { + return this.data.order; + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function () { + function TransformConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return TransformConstraintData; + }()); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IntSet = (function () { + function IntSet() { + this.array = new Array(); + } + IntSet.prototype.add = function (value) { + var contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + }; + IntSet.prototype.contains = function (value) { + return this.array[value | 0] != undefined; + }; + IntSet.prototype.remove = function (value) { + this.array[value | 0] = undefined; + }; + IntSet.prototype.clear = function () { + this.array.length = 0; + }; + return IntSet; + }()); + spine.IntSet = IntSet; + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + }; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + }; + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + }; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; + }()); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { + } + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); + }; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); + }; + MathUtils.signum = function (value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + }; + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + }; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + }; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; + }()); + spine.MathUtils = MathUtils; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; + } + return array; + }; + Utils.ensureArrayCapacity = function (array, size, value) { + if (value === void 0) { value = 0; } + if (array.length >= size) + return array; + return Utils.setArraySize(array, size, value); + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; + }()); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { + } + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + }; + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + }; + Pool.prototype.free = function (item) { + if (item.reset) + item.reset(); + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) { + if (items[i].reset) + items[i].reset(); + this.items[i] = items[i]; + } + }; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; + }()); + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; + } + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; + }()); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; + } + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + }; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; +})(spine || (spine = {})); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/lib/3.6/spine-canvas.js b/release/MAC版本/lib/3.6/spine-canvas.js new file mode 100644 index 0000000..1dc5765 --- /dev/null +++ b/release/MAC版本/lib/3.6/spine-canvas.js @@ -0,0 +1,6860 @@ +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var spine; +(function (spine) { + var Animation = (function () { + function Animation(name, timelines, duration) { + if (name == null) + throw new Error("name cannot be null."); + if (timelines == null) + throw new Error("timelines cannot be null."); + this.name = name; + this.timelines = timelines; + this.duration = duration; + } + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, pose, direction) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction); + }; + Animation.binarySearch = function (values, target, step) { + if (step === void 0) { step = 1; } + var low = 0; + var high = values.length / step - 2; + if (high == 0) + return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) + return (low + 1) * step; + current = (low + high) >>> 1; + } + }; + Animation.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) + return i; + return -1; + }; + return Animation; + }()); + spine.Animation = Animation; + var MixPose; + (function (MixPose) { + MixPose[MixPose["setup"] = 0] = "setup"; + MixPose[MixPose["current"] = 1] = "current"; + MixPose[MixPose["currentLayered"] = 2] = "currentLayered"; + })(MixPose = spine.MixPose || (spine.MixPose = {})); + var MixDirection; + (function (MixDirection) { + MixDirection[MixDirection["in"] = 0] = "in"; + MixDirection[MixDirection["out"] = 1] = "out"; + })(MixDirection = spine.MixDirection || (spine.MixDirection = {})); + var TimelineType; + (function (TimelineType) { + TimelineType[TimelineType["rotate"] = 0] = "rotate"; + TimelineType[TimelineType["translate"] = 1] = "translate"; + TimelineType[TimelineType["scale"] = 2] = "scale"; + TimelineType[TimelineType["shear"] = 3] = "shear"; + TimelineType[TimelineType["attachment"] = 4] = "attachment"; + TimelineType[TimelineType["color"] = 5] = "color"; + TimelineType[TimelineType["deform"] = 6] = "deform"; + TimelineType[TimelineType["event"] = 7] = "event"; + TimelineType[TimelineType["drawOrder"] = 8] = "drawOrder"; + TimelineType[TimelineType["ikConstraint"] = 9] = "ikConstraint"; + TimelineType[TimelineType["transformConstraint"] = 10] = "transformConstraint"; + TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; + TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; + TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; + TimelineType[TimelineType["twoColor"] = 14] = "twoColor"; + })(TimelineType = spine.TimelineType || (spine.TimelineType = {})); + var CurveTimeline = (function () { + function CurveTimeline(frameCount) { + if (frameCount <= 0) + throw new Error("frameCount must be > 0: " + frameCount); + this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE); + } + CurveTimeline.prototype.getFrameCount = function () { + return this.curves.length / CurveTimeline.BEZIER_SIZE + 1; + }; + CurveTimeline.prototype.setLinear = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR; + }; + CurveTimeline.prototype.setStepped = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED; + }; + CurveTimeline.prototype.getCurveType = function (frameIndex) { + var index = frameIndex * CurveTimeline.BEZIER_SIZE; + if (index == this.curves.length) + return CurveTimeline.LINEAR; + var type = this.curves[index]; + if (type == CurveTimeline.LINEAR) + return CurveTimeline.LINEAR; + if (type == CurveTimeline.STEPPED) + return CurveTimeline.STEPPED; + return CurveTimeline.BEZIER; + }; + CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) { + var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03; + var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; + var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var curves = this.curves; + curves[i++] = CurveTimeline.BEZIER; + var x = dfx, y = dfy; + for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + }; + CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) { + percent = spine.MathUtils.clamp(percent, 0, 1); + var curves = this.curves; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var type = curves[i]; + if (type == CurveTimeline.LINEAR) + return percent; + if (type == CurveTimeline.STEPPED) + return 0; + i++; + var x = 0; + for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + x = curves[i]; + if (x >= percent) { + var prevX = void 0, prevY = void 0; + if (i == start) { + prevX = 0; + prevY = 0; + } + else { + prevX = curves[i - 2]; + prevY = curves[i - 1]; + } + return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + var y = curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); + }; + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; + return CurveTimeline; + }()); + spine.CurveTimeline = CurveTimeline; + var RotateTimeline = (function (_super) { + __extends(RotateTimeline, _super); + function RotateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount << 1); + return _this; + } + RotateTimeline.prototype.getPropertyId = function () { + return (TimelineType.rotate << 24) + this.boneIndex; + }; + RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) { + frameIndex <<= 1; + this.frames[frameIndex] = time; + this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; + }; + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + bone.rotation = bone.data.rotation; + return; + case MixPose.current: + var r_1 = bone.data.rotation - bone.rotation; + r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; + bone.rotation += r_1 * alpha; + } + return; + } + if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { + if (pose == MixPose.setup) + bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha; + else { + var r_2 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; + r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360; + bone.rotation += r_2 * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES); + var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); + var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + r = prevRotation + r * percent; + if (pose == MixPose.setup) { + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.rotation = bone.data.rotation + r * alpha; + } + else { + r = bone.data.rotation + r - bone.rotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.rotation += r * alpha; + } + }; + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; + return RotateTimeline; + }(CurveTimeline)); + spine.RotateTimeline = RotateTimeline; + var TranslateTimeline = (function (_super) { + __extends(TranslateTimeline, _super); + function TranslateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + return _this; + } + TranslateTimeline.prototype.getPropertyId = function () { + return (TimelineType.translate << 24) + this.boneIndex; + }; + TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) { + frameIndex *= TranslateTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TranslateTimeline.X] = x; + this.frames[frameIndex + TranslateTimeline.Y] = y; + }; + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixPose.current: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) { + x = frames[frames.length + TranslateTimeline.PREV_X]; + y = frames[frames.length + TranslateTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES); + x = frames[frame + TranslateTimeline.PREV_X]; + y = frames[frame + TranslateTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime)); + x += (frames[frame + TranslateTimeline.X] - x) * percent; + y += (frames[frame + TranslateTimeline.Y] - y) * percent; + } + if (pose == MixPose.setup) { + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + } + else { + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + } + }; + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; + return TranslateTimeline; + }(CurveTimeline)); + spine.TranslateTimeline = TranslateTimeline; + var ScaleTimeline = (function (_super) { + __extends(ScaleTimeline, _super); + function ScaleTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ScaleTimeline.prototype.getPropertyId = function () { + return (TimelineType.scale << 24) + this.boneIndex; + }; + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixPose.current: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) { + x = frames[frames.length + ScaleTimeline.PREV_X] * bone.data.scaleX; + y = frames[frames.length + ScaleTimeline.PREV_Y] * bone.data.scaleY; + } + else { + var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES); + x = frames[frame + ScaleTimeline.PREV_X]; + y = frames[frame + ScaleTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime)); + x = (x + (frames[frame + ScaleTimeline.X] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY; + } + if (alpha == 1) { + bone.scaleX = x; + bone.scaleY = y; + } + else { + var bx = 0, by = 0; + if (pose == MixPose.setup) { + bx = bone.data.scaleX; + by = bone.data.scaleY; + } + else { + bx = bone.scaleX; + by = bone.scaleY; + } + if (direction == MixDirection.out) { + x = Math.abs(x) * spine.MathUtils.signum(bx); + y = Math.abs(y) * spine.MathUtils.signum(by); + } + else { + bx = Math.abs(bx) * spine.MathUtils.signum(x); + by = Math.abs(by) * spine.MathUtils.signum(y); + } + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + } + }; + return ScaleTimeline; + }(TranslateTimeline)); + spine.ScaleTimeline = ScaleTimeline; + var ShearTimeline = (function (_super) { + __extends(ShearTimeline, _super); + function ShearTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ShearTimeline.prototype.getPropertyId = function () { + return (TimelineType.shear << 24) + this.boneIndex; + }; + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixPose.current: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ShearTimeline.ENTRIES]) { + x = frames[frames.length + ShearTimeline.PREV_X]; + y = frames[frames.length + ShearTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES); + x = frames[frame + ShearTimeline.PREV_X]; + y = frames[frame + ShearTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime)); + x = x + (frames[frame + ShearTimeline.X] - x) * percent; + y = y + (frames[frame + ShearTimeline.Y] - y) * percent; + } + if (pose == MixPose.setup) { + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + } + else { + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + } + }; + return ShearTimeline; + }(TranslateTimeline)); + spine.ShearTimeline = ShearTimeline; + var ColorTimeline = (function (_super) { + __extends(ColorTimeline, _super); + function ColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + return _this; + } + ColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.color << 24) + this.slotIndex; + }; + ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) { + frameIndex *= ColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + ColorTimeline.R] = r; + this.frames[frameIndex + ColorTimeline.G] = g; + this.frames[frameIndex + ColorTimeline.B] = b; + this.frames[frameIndex + ColorTimeline.A] = a; + }; + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + return; + case MixPose.current: + var color = slot.color, setup = slot.data.color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } + return; + } + var r = 0, g = 0, b = 0, a = 0; + if (time >= frames[frames.length - ColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + ColorTimeline.PREV_R]; + g = frames[i + ColorTimeline.PREV_G]; + b = frames[i + ColorTimeline.PREV_B]; + a = frames[i + ColorTimeline.PREV_A]; + } + else { + var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES); + r = frames[frame + ColorTimeline.PREV_R]; + g = frames[frame + ColorTimeline.PREV_G]; + b = frames[frame + ColorTimeline.PREV_B]; + a = frames[frame + ColorTimeline.PREV_A]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + ColorTimeline.R] - r) * percent; + g += (frames[frame + ColorTimeline.G] - g) * percent; + b += (frames[frame + ColorTimeline.B] - b) * percent; + a += (frames[frame + ColorTimeline.A] - a) * percent; + } + if (alpha == 1) + slot.color.set(r, g, b, a); + else { + var color = slot.color; + if (pose == MixPose.setup) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + }; + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; + return ColorTimeline; + }(CurveTimeline)); + spine.ColorTimeline = ColorTimeline; + var TwoColorTimeline = (function (_super) { + __extends(TwoColorTimeline, _super); + function TwoColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES); + return _this; + } + TwoColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.twoColor << 24) + this.slotIndex; + }; + TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + }; + TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + return; + case MixPose.current: + var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0); + } + return; + } + var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + TwoColorTimeline.PREV_R]; + g = frames[i + TwoColorTimeline.PREV_G]; + b = frames[i + TwoColorTimeline.PREV_B]; + a = frames[i + TwoColorTimeline.PREV_A]; + r2 = frames[i + TwoColorTimeline.PREV_R2]; + g2 = frames[i + TwoColorTimeline.PREV_G2]; + b2 = frames[i + TwoColorTimeline.PREV_B2]; + } + else { + var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES); + r = frames[frame + TwoColorTimeline.PREV_R]; + g = frames[frame + TwoColorTimeline.PREV_G]; + b = frames[frame + TwoColorTimeline.PREV_B]; + a = frames[frame + TwoColorTimeline.PREV_A]; + r2 = frames[frame + TwoColorTimeline.PREV_R2]; + g2 = frames[frame + TwoColorTimeline.PREV_G2]; + b2 = frames[frame + TwoColorTimeline.PREV_B2]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + TwoColorTimeline.R] - r) * percent; + g += (frames[frame + TwoColorTimeline.G] - g) * percent; + b += (frames[frame + TwoColorTimeline.B] - b) * percent; + a += (frames[frame + TwoColorTimeline.A] - a) * percent; + r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent; + g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent; + b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent; + } + if (alpha == 1) { + slot.color.set(r, g, b, a); + slot.darkColor.set(r2, g2, b2, 1); + } + else { + var light = slot.color, dark = slot.darkColor; + if (pose == MixPose.setup) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + }; + TwoColorTimeline.ENTRIES = 8; + TwoColorTimeline.PREV_TIME = -8; + TwoColorTimeline.PREV_R = -7; + TwoColorTimeline.PREV_G = -6; + TwoColorTimeline.PREV_B = -5; + TwoColorTimeline.PREV_A = -4; + TwoColorTimeline.PREV_R2 = -3; + TwoColorTimeline.PREV_G2 = -2; + TwoColorTimeline.PREV_B2 = -1; + TwoColorTimeline.R = 1; + TwoColorTimeline.G = 2; + TwoColorTimeline.B = 3; + TwoColorTimeline.A = 4; + TwoColorTimeline.R2 = 5; + TwoColorTimeline.G2 = 6; + TwoColorTimeline.B2 = 7; + return TwoColorTimeline; + }(CurveTimeline)); + spine.TwoColorTimeline = TwoColorTimeline; + var AttachmentTimeline = (function () { + function AttachmentTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.attachmentNames = new Array(frameCount); + } + AttachmentTimeline.prototype.getPropertyId = function () { + return (TimelineType.attachment << 24) + this.slotIndex; + }; + AttachmentTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }; + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (direction == MixDirection.out && pose == MixPose.setup) { + var attachmentName_1 = slot.data.attachmentName; + slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1)); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (pose == MixPose.setup) { + var attachmentName_2 = slot.data.attachmentName; + slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2)); + } + return; + } + var frameIndex = 0; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = Animation.binarySearch(frames, time, 1) - 1; + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex] + .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + return AttachmentTimeline; + }()); + spine.AttachmentTimeline = AttachmentTimeline; + var zeros = null; + var DeformTimeline = (function (_super) { + __extends(DeformTimeline, _super); + function DeformTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount); + _this.frameVertices = new Array(frameCount); + if (zeros == null) + zeros = spine.Utils.newFloatArray(64); + return _this; + } + DeformTimeline.prototype.getPropertyId = function () { + return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex; + }; + DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { + this.frames[frameIndex] = time; + this.frameVertices[frameIndex] = vertices; + }; + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + var slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) + return; + var verticesArray = slot.attachmentVertices; + if (verticesArray.length == 0) + alpha = 1; + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + var frames = this.frames; + if (time < frames[0]) { + var vertexAttachment = slotAttachment; + switch (pose) { + case MixPose.setup: + verticesArray.length = 0; + return; + case MixPose.current: + if (alpha == 1) { + verticesArray.length = 0; + break; + } + var vertices_1 = spine.Utils.setArraySize(verticesArray, vertexCount); + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] += (setupVertices[i] - vertices_1[i]) * alpha; + } + else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] *= alpha; + } + } + return; + } + var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); + if (time >= frames[frames.length - 1]) { + var lastVertices = frameVertices[frames.length - 1]; + if (alpha == 1) { + spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); + } + else if (pose == MixPose.setup) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices_1 = vertexAttachment.vertices; + for (var i_1 = 0; i_1 < vertexCount; i_1++) { + var setup = setupVertices_1[i_1]; + vertices[i_1] = setup + (lastVertices[i_1] - setup) * alpha; + } + } + else { + for (var i_2 = 0; i_2 < vertexCount; i_2++) + vertices[i_2] = lastVertices[i_2] * alpha; + } + } + else { + for (var i_3 = 0; i_3 < vertexCount; i_3++) + vertices[i_3] += (lastVertices[i_3] - vertices[i_3]) * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time); + var prevVertices = frameVertices[frame - 1]; + var nextVertices = frameVertices[frame]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + if (alpha == 1) { + for (var i_4 = 0; i_4 < vertexCount; i_4++) { + var prev = prevVertices[i_4]; + vertices[i_4] = prev + (nextVertices[i_4] - prev) * percent; + } + } + else if (pose == MixPose.setup) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices_2 = vertexAttachment.vertices; + for (var i_5 = 0; i_5 < vertexCount; i_5++) { + var prev = prevVertices[i_5], setup = setupVertices_2[i_5]; + vertices[i_5] = setup + (prev + (nextVertices[i_5] - prev) * percent - setup) * alpha; + } + } + else { + for (var i_6 = 0; i_6 < vertexCount; i_6++) { + var prev = prevVertices[i_6]; + vertices[i_6] = (prev + (nextVertices[i_6] - prev) * percent) * alpha; + } + } + } + else { + for (var i_7 = 0; i_7 < vertexCount; i_7++) { + var prev = prevVertices[i_7]; + vertices[i_7] += (prev + (nextVertices[i_7] - prev) * percent - vertices[i_7]) * alpha; + } + } + }; + return DeformTimeline; + }(CurveTimeline)); + spine.DeformTimeline = DeformTimeline; + var EventTimeline = (function () { + function EventTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.events = new Array(frameCount); + } + EventTimeline.prototype.getPropertyId = function () { + return TimelineType.event << 24; + }; + EventTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + EventTimeline.prototype.setFrame = function (frameIndex, event) { + this.frames[frameIndex] = event.time; + this.events[frameIndex] = event; + }; + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + if (firedEvents == null) + return; + var frames = this.frames; + var frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, pose, direction); + lastTime = -1; + } + else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + var frame = 0; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.binarySearch(frames, lastTime); + var frameTime = frames[frame]; + while (frame > 0) { + if (frames[frame - 1] != frameTime) + break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.push(this.events[frame]); + }; + return EventTimeline; + }()); + spine.EventTimeline = EventTimeline; + var DrawOrderTimeline = (function () { + function DrawOrderTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.drawOrders = new Array(frameCount); + } + DrawOrderTimeline.prototype.getPropertyId = function () { + return TimelineType.drawOrder << 24; + }; + DrawOrderTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) { + this.frames[frameIndex] = time; + this.drawOrders[frameIndex] = drawOrder; + }; + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var drawOrder = skeleton.drawOrder; + var slots = skeleton.slots; + if (direction == MixDirection.out && pose == MixPose.setup) { + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (pose == MixPose.setup) + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frame = 0; + if (time >= frames[frames.length - 1]) + frame = frames.length - 1; + else + frame = Animation.binarySearch(frames, time) - 1; + var drawOrderToSetupIndex = this.drawOrders[frame]; + if (drawOrderToSetupIndex == null) + spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length); + else { + for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + }; + return DrawOrderTimeline; + }()); + spine.DrawOrderTimeline = DrawOrderTimeline; + var IkConstraintTimeline = (function (_super) { + __extends(IkConstraintTimeline, _super); + function IkConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + return _this; + } + IkConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; + }; + IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection) { + frameIndex *= IkConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; + this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; + }; + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var frames = this.frames; + var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + return; + case MixPose.current: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + } + return; + } + if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { + if (pose == MixPose.setup) { + constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection + : frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + else { + constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; + if (direction == MixDirection["in"]) + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + return; + } + var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES); + var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); + if (pose == MixPose.setup) { + constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + else { + constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; + if (direction == MixDirection["in"]) + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + } + }; + IkConstraintTimeline.ENTRIES = 3; + IkConstraintTimeline.PREV_TIME = -3; + IkConstraintTimeline.PREV_MIX = -2; + IkConstraintTimeline.PREV_BEND_DIRECTION = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.BEND_DIRECTION = 2; + return IkConstraintTimeline; + }(CurveTimeline)); + spine.IkConstraintTimeline = IkConstraintTimeline; + var TransformConstraintTimeline = (function (_super) { + __extends(TransformConstraintTimeline, _super); + function TransformConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + return _this; + } + TransformConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; + }; + TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) { + frameIndex *= TransformConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix; + this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; + this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; + }; + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var frames = this.frames; + var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (time < frames[0]) { + var data = constraint.data; + switch (pose) { + case MixPose.setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixPose.current: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; + } + return; + } + var rotate = 0, translate = 0, scale = 0, shear = 0; + if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) { + var i = frames.length; + rotate = frames[i + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[i + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[i + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[i + TransformConstraintTimeline.PREV_SHEAR]; + } + else { + var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES); + rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[frame + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent; + scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; + shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; + } + if (pose == MixPose.setup) { + var data = constraint.data; + constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; + constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; + constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; + constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + constraint.scaleMix += (scale - constraint.scaleMix) * alpha; + constraint.shearMix += (shear - constraint.shearMix) * alpha; + } + }; + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; + return TransformConstraintTimeline; + }(CurveTimeline)); + spine.TransformConstraintTimeline = TransformConstraintTimeline; + var PathConstraintPositionTimeline = (function (_super) { + __extends(PathConstraintPositionTimeline, _super); + function PathConstraintPositionTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + return _this; + } + PathConstraintPositionTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; + }; + PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) { + frameIndex *= PathConstraintPositionTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; + }; + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + constraint.position = constraint.data.position; + return; + case MixPose.current: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } + return; + } + var position = 0; + if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES]) + position = frames[frames.length + PathConstraintPositionTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES); + position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); + position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; + } + if (pose == MixPose.setup) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + }; + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; + return PathConstraintPositionTimeline; + }(CurveTimeline)); + spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; + var PathConstraintSpacingTimeline = (function (_super) { + __extends(PathConstraintSpacingTimeline, _super); + function PathConstraintSpacingTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + PathConstraintSpacingTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; + }; + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + constraint.spacing = constraint.data.spacing; + return; + case MixPose.current: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } + return; + } + var spacing = 0; + if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES]) + spacing = frames[frames.length + PathConstraintSpacingTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES); + spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); + spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; + } + if (pose == MixPose.setup) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + }; + return PathConstraintSpacingTimeline; + }(PathConstraintPositionTimeline)); + spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline; + var PathConstraintMixTimeline = (function (_super) { + __extends(PathConstraintMixTimeline, _super); + function PathConstraintMixTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + return _this; + } + PathConstraintMixTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; + }; + PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) { + frameIndex *= PathConstraintMixTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; + }; + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixPose.current: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; + } + return; + } + var rotate = 0, translate = 0; + if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) { + rotate = frames[frames.length + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frames.length + PathConstraintMixTimeline.PREV_TRANSLATE]; + } + else { + var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES); + rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; + } + if (pose == MixPose.setup) { + constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; + constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + } + }; + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; + return PathConstraintMixTimeline; + }(CurveTimeline)); + spine.PathConstraintMixTimeline = PathConstraintMixTimeline; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationState = (function () { + function AnimationState(data) { + this.tracks = new Array(); + this.events = new Array(); + this.listeners = new Array(); + this.queue = new EventQueue(this); + this.propertyIDs = new spine.IntSet(); + this.mixingTo = new Array(); + this.animationsChanged = false; + this.timeScale = 1; + this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); + this.data = data; + } + AnimationState.prototype.update = function (delta) { + delta *= this.timeScale; + var tracks = this.tracks; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + var currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + var next = current.next; + if (next != null) { + var nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime = nextTime + delta * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom != null) { + next.mixTime += currentDelta; + next = next.mixingFrom; + } + continue; + } + } + else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) { + var from = current.mixingFrom; + current.mixingFrom = null; + while (from != null) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + }; + AnimationState.prototype.updateMixingFrom = function (to, delta) { + var from = to.mixingFrom; + if (from == null) + return true; + var finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta * to.timeScale; + return false; + }; + AnimationState.prototype.apply = function (skeleton) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + var events = this.events; + var tracks = this.tracks; + var applied = false; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null || current.delay > 0) + continue; + applied = true; + var currentPose = i == 0 ? spine.MixPose.current : spine.MixPose.currentLayered; + var mix = current.alpha; + if (current.mixingFrom != null) + mix *= this.applyMixingFrom(current, skeleton, currentPose); + else if (current.trackTime >= current.trackEnd && current.next == null) + mix = 0; + var animationLast = current.animationLast, animationTime = current.getAnimationTime(); + var timelineCount = current.animation.timelines.length; + var timelines = current.animation.timelines; + if (mix == 1) { + for (var ii = 0; ii < timelineCount; ii++) + timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, spine.MixPose.setup, spine.MixDirection["in"]); + } + else { + var timelineData = current.timelineData; + var firstFrame = current.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = current.timelinesRotation; + for (var ii = 0; ii < timelineCount; ii++) { + var timeline = timelines[ii]; + var pose = timelineData[ii] >= AnimationState.FIRST ? spine.MixPose.setup : currentPose; + if (timeline instanceof spine.RotateTimeline) { + this.applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + } + else { + spine.Utils.webkit602BugfixHelper(mix, pose); + timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, spine.MixDirection["in"]); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + this.queue.drain(); + return applied; + }; + AnimationState.prototype.applyMixingFrom = function (to, skeleton, currentPose) { + var from = to.mixingFrom; + if (from.mixingFrom != null) + this.applyMixingFrom(from, skeleton, currentPose); + var mix = 0; + if (to.mixDuration == 0) { + mix = 1; + currentPose = spine.MixPose.setup; + } + else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + } + var events = mix < from.eventThreshold ? this.events : null; + var attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + var animationLast = from.animationLast, animationTime = from.getAnimationTime(); + var timelineCount = from.animation.timelines.length; + var timelines = from.animation.timelines; + var timelineData = from.timelineData; + var timelineDipMix = from.timelineDipMix; + var firstFrame = from.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = from.timelinesRotation; + var pose; + var alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha = 0; + from.totalAlpha = 0; + for (var i = 0; i < timelineCount; i++) { + var timeline = timelines[i]; + switch (timelineData[i]) { + case AnimationState.SUBSEQUENT: + if (!attachments && timeline instanceof spine.AttachmentTimeline) + continue; + if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) + continue; + pose = currentPose; + alpha = alphaMix; + break; + case AnimationState.FIRST: + pose = spine.MixPose.setup; + alpha = alphaMix; + break; + case AnimationState.DIP: + pose = spine.MixPose.setup; + alpha = alphaDip; + break; + default: + pose = spine.MixPose.setup; + alpha = alphaDip; + var dipMix = timelineDipMix[i]; + alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + else { + spine.Utils.webkit602BugfixHelper(alpha, pose); + timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, spine.MixDirection.out); + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + }; + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, pose, spine.MixDirection["in"]); + return; + } + var rotateTimeline = timeline; + var frames = rotateTimeline.frames; + var bone = skeleton.bones[rotateTimeline.boneIndex]; + if (time < frames[0]) { + if (pose == spine.MixPose.setup) + bone.rotation = bone.data.rotation; + return; + } + var r2 = 0; + if (time >= frames[frames.length - spine.RotateTimeline.ENTRIES]) + r2 = bone.data.rotation + frames[frames.length + spine.RotateTimeline.PREV_ROTATION]; + else { + var frame = spine.Animation.binarySearch(frames, time, spine.RotateTimeline.ENTRIES); + var prevRotation = frames[frame + spine.RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + spine.RotateTimeline.PREV_TIME] - frameTime)); + r2 = frames[frame + spine.RotateTimeline.ROTATION] - prevRotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + r2 = prevRotation + r2 * percent + bone.data.rotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + } + var r1 = pose == spine.MixPose.setup ? bone.data.rotation : bone.rotation; + var total = 0, diff = r2 - r1; + if (diff == 0) { + total = timelinesRotation[i]; + } + else { + diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360; + var lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } + else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + var current = diff > 0, dir = lastTotal >= 0; + if (spine.MathUtils.signum(lastDiff) != spine.MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * spine.MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * spine.MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360; + }; + AnimationState.prototype.queueEvents = function (entry, animationTime) { + var animationStart = entry.animationStart, animationEnd = entry.animationEnd; + var duration = animationEnd - animationStart; + var trackLastWrapped = entry.trackLast % duration; + var events = this.events; + var i = 0, n = events.length; + for (; i < n; i++) { + var event_1 = events[i]; + if (event_1.time < trackLastWrapped) + break; + if (event_1.time > animationEnd) + continue; + this.queue.event(entry, event_1); + } + var complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + var event_2 = events[i]; + if (event_2.time < animationStart) + continue; + this.queue.event(entry, events[i]); + } + }; + AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.clearTrack = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return; + var current = this.tracks[trackIndex]; + if (current == null) + return; + this.queue.end(current); + this.disposeNext(current); + var entry = current; + while (true) { + var from = entry.mixingFrom; + if (from == null) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + }; + AnimationState.prototype.setCurrent = function (index, current, interrupt) { + var from = this.expandToIndex(index); + this.tracks[index] = current; + if (from != null) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + current.mixTime = 0; + if (from.mixingFrom != null && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + }; + AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + }; + AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) { + if (animation == null) + throw new Error("animation cannot be null."); + var interrupt = true; + var current = this.expandToIndex(trackIndex); + if (current != null) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.disposeNext(current); + current = current.mixingFrom; + interrupt = false; + } + else + this.disposeNext(current); + } + var entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + }; + AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + }; + AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) { + if (animation == null) + throw new Error("animation cannot be null."); + var last = this.expandToIndex(trackIndex); + if (last != null) { + while (last.next != null) + last = last.next; + } + var entry = this.trackEntry(trackIndex, animation, loop, last); + if (last == null) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } + else { + last.next = entry; + if (delay <= 0) { + var duration = last.animationEnd - last.animationStart; + if (duration != 0) { + if (last.loop) + delay += duration * (1 + ((last.trackTime / duration) | 0)); + else + delay += duration; + delay -= this.data.getMix(last.animation, animation); + } + else + delay = 0; + } + } + entry.delay = delay; + return entry; + }; + AnimationState.prototype.setEmptyAnimation = function (trackIndex, mixDuration) { + var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.addEmptyAnimation = function (trackIndex, mixDuration, delay) { + if (delay <= 0) + delay -= mixDuration; + var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) { + var current = this.tracks[i]; + if (current != null) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.expandToIndex = function (index) { + if (index < this.tracks.length) + return this.tracks[index]; + spine.Utils.ensureArrayCapacity(this.tracks, index - this.tracks.length + 1, null); + this.tracks.length = index + 1; + return null; + }; + AnimationState.prototype.trackEntry = function (trackIndex, animation, loop, last) { + var entry = this.trackEntryPool.obtain(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.interruptAlpha = 1; + entry.mixTime = 0; + entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); + return entry; + }; + AnimationState.prototype.disposeNext = function (entry) { + var next = entry.next; + while (next != null) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + }; + AnimationState.prototype._animationsChanged = function () { + this.animationsChanged = false; + var propertyIDs = this.propertyIDs; + propertyIDs.clear(); + var mixingTo = this.mixingTo; + for (var i = 0, n = this.tracks.length; i < n; i++) { + var entry = this.tracks[i]; + if (entry != null) + entry.setTimelineData(null, mixingTo, propertyIDs); + } + }; + AnimationState.prototype.getCurrent = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + }; + AnimationState.prototype.addListener = function (listener) { + if (listener == null) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + }; + AnimationState.prototype.removeListener = function (listener) { + var index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + }; + AnimationState.prototype.clearListeners = function () { + this.listeners.length = 0; + }; + AnimationState.prototype.clearListenerNotifications = function () { + this.queue.clear(); + }; + AnimationState.emptyAnimation = new spine.Animation("", [], 0); + AnimationState.SUBSEQUENT = 0; + AnimationState.FIRST = 1; + AnimationState.DIP = 2; + AnimationState.DIP_MIX = 3; + return AnimationState; + }()); + spine.AnimationState = AnimationState; + var TrackEntry = (function () { + function TrackEntry() { + this.timelineData = new Array(); + this.timelineDipMix = new Array(); + this.timelinesRotation = new Array(); + } + TrackEntry.prototype.reset = function () { + this.next = null; + this.mixingFrom = null; + this.animation = null; + this.listener = null; + this.timelineData.length = 0; + this.timelineDipMix.length = 0; + this.timelinesRotation.length = 0; + }; + TrackEntry.prototype.setTimelineData = function (to, mixingToArray, propertyIDs) { + if (to != null) + mixingToArray.push(to); + var lastEntry = this.mixingFrom != null ? this.mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this; + if (to != null) + mixingToArray.pop(); + var mixingTo = mixingToArray; + var mixingToLast = mixingToArray.length - 1; + var timelines = this.animation.timelines; + var timelinesCount = this.animation.timelines.length; + var timelineData = spine.Utils.setArraySize(this.timelineData, timelinesCount); + this.timelineDipMix.length = 0; + var timelineDipMix = spine.Utils.setArraySize(this.timelineDipMix, timelinesCount); + outer: for (var i = 0; i < timelinesCount; i++) { + var id = timelines[i].getPropertyId(); + if (!propertyIDs.add(id)) + timelineData[i] = AnimationState.SUBSEQUENT; + else if (to == null || !to.hasTimeline(id)) + timelineData[i] = AnimationState.FIRST; + else { + for (var ii = mixingToLast; ii >= 0; ii--) { + var entry = mixingTo[ii]; + if (!entry.hasTimeline(id)) { + if (entry.mixDuration > 0) { + timelineData[i] = AnimationState.DIP_MIX; + timelineDipMix[i] = entry; + continue outer; + } + } + } + timelineData[i] = AnimationState.DIP; + } + } + return lastEntry; + }; + TrackEntry.prototype.hasTimeline = function (id) { + var timelines = this.animation.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + if (timelines[i].getPropertyId() == id) + return true; + return false; + }; + TrackEntry.prototype.getAnimationTime = function () { + if (this.loop) { + var duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return (this.trackTime % duration) + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + }; + TrackEntry.prototype.setAnimationLast = function (animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + }; + TrackEntry.prototype.isComplete = function () { + return this.trackTime >= this.animationEnd - this.animationStart; + }; + TrackEntry.prototype.resetRotationDirections = function () { + this.timelinesRotation.length = 0; + }; + return TrackEntry; + }()); + spine.TrackEntry = TrackEntry; + var EventQueue = (function () { + function EventQueue(animState) { + this.objects = []; + this.drainDisabled = false; + this.animState = animState; + } + EventQueue.prototype.start = function (entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.interrupt = function (entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + }; + EventQueue.prototype.end = function (entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.dispose = function (entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + }; + EventQueue.prototype.complete = function (entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + }; + EventQueue.prototype.event = function (entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + }; + EventQueue.prototype.drain = function () { + if (this.drainDisabled) + return; + this.drainDisabled = true; + var objects = this.objects; + var listeners = this.animState.listeners; + for (var i = 0; i < objects.length; i += 2) { + var type = objects[i]; + var entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener != null && entry.listener.start) + entry.listener.start(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].start) + listeners[ii].start(entry); + break; + case EventType.interrupt: + if (entry.listener != null && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].interrupt) + listeners[ii].interrupt(entry); + break; + case EventType.end: + if (entry.listener != null && entry.listener.end) + entry.listener.end(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].end) + listeners[ii].end(entry); + case EventType.dispose: + if (entry.listener != null && entry.listener.dispose) + entry.listener.dispose(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].dispose) + listeners[ii].dispose(entry); + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener != null && entry.listener.complete) + entry.listener.complete(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].complete) + listeners[ii].complete(entry); + break; + case EventType.event: + var event_3 = objects[i++ + 2]; + if (entry.listener != null && entry.listener.event) + entry.listener.event(entry, event_3); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].event) + listeners[ii].event(entry, event_3); + break; + } + } + this.clear(); + this.drainDisabled = false; + }; + EventQueue.prototype.clear = function () { + this.objects.length = 0; + }; + return EventQueue; + }()); + spine.EventQueue = EventQueue; + var EventType; + (function (EventType) { + EventType[EventType["start"] = 0] = "start"; + EventType[EventType["interrupt"] = 1] = "interrupt"; + EventType[EventType["end"] = 2] = "end"; + EventType[EventType["dispose"] = 3] = "dispose"; + EventType[EventType["complete"] = 4] = "complete"; + EventType[EventType["event"] = 5] = "event"; + })(EventType = spine.EventType || (spine.EventType = {})); + var AnimationStateAdapter2 = (function () { + function AnimationStateAdapter2() { + } + AnimationStateAdapter2.prototype.start = function (entry) { + }; + AnimationStateAdapter2.prototype.interrupt = function (entry) { + }; + AnimationStateAdapter2.prototype.end = function (entry) { + }; + AnimationStateAdapter2.prototype.dispose = function (entry) { + }; + AnimationStateAdapter2.prototype.complete = function (entry) { + }; + AnimationStateAdapter2.prototype.event = function (entry, event) { + }; + return AnimationStateAdapter2; + }()); + spine.AnimationStateAdapter2 = AnimationStateAdapter2; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationStateData = (function () { + function AnimationStateData(skeletonData) { + this.animationToMixTime = {}; + this.defaultMix = 0; + if (skeletonData == null) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + AnimationStateData.prototype.setMix = function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (from == null) + throw new Error("Animation not found: " + fromName); + var to = this.skeletonData.findAnimation(toName); + if (to == null) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + }; + AnimationStateData.prototype.setMixWith = function (from, to, duration) { + if (from == null) + throw new Error("from cannot be null."); + if (to == null) + throw new Error("to cannot be null."); + var key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + }; + AnimationStateData.prototype.getMix = function (from, to) { + var key = from.name + "." + to.name; + var value = this.animationToMixTime[key]; + return value === undefined ? this.defaultMix : value; + }; + return AnimationStateData; + }()); + spine.AnimationStateData = AnimationStateData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AssetManager = (function () { + function AssetManager(textureLoader, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + } + AssetManager.downloadText = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.onload = function () { + if (request.status == 200) { + success(request.responseText); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.downloadBinary = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status == 200) { + success(new Uint8Array(request.response)); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.prototype.loadText = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + AssetManager.downloadText(path, function (data) { + _this.assets[path] = data; + if (success) + success(path, data); + _this.toLoad--; + _this.loaded++; + }, function (state, responseText) { + _this.errors[path] = "Couldn't load text " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load text " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.loadTexture = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + img.src = path; + }; + AssetManager.prototype.loadTextureData = function (path, data, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + img.src = data; + }; + AssetManager.prototype.loadTextureAtlas = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : ""; + path = this.pathPrefix + path; + this.toLoad++; + AssetManager.downloadText(path, function (atlasData) { + var pagesLoaded = { count: 0 }; + var atlasPages = new Array(); + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + atlasPages.push(parent + "/" + path); + var image = document.createElement("img"); + image.width = 16; + image.height = 16; + return new spine.FakeTexture(image); + }); + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + return; + } + var _loop_1 = function (atlasPage) { + var pageLoadError = false; + _this.loadTexture(atlasPage, function (imagePath, image) { + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + if (!pageLoadError) { + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + return _this.get(parent + "/" + path); + }); + _this.assets[path] = atlas; + if (success) + success(path, atlas); + _this.toLoad--; + _this.loaded++; + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + } + } + else { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + } + }, function (imagePath, errorMessage) { + pageLoadError = true; + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + }); + }; + for (var _i = 0, atlasPages_1 = atlasPages; _i < atlasPages_1.length; _i++) { + var atlasPage = atlasPages_1[_i]; + _loop_1(atlasPage); + } + }, function (state, responseText) { + _this.errors[path] = "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.get = function (path) { + path = this.pathPrefix + path; + return this.assets[path]; + }; + AssetManager.prototype.remove = function (path) { + path = this.pathPrefix + path; + var asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + this.assets[path] = null; + }; + AssetManager.prototype.removeAll = function () { + for (var key in this.assets) { + var asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + }; + AssetManager.prototype.isLoadingComplete = function () { + return this.toLoad == 0; + }; + AssetManager.prototype.getToLoad = function () { + return this.toLoad; + }; + AssetManager.prototype.getLoaded = function () { + return this.loaded; + }; + AssetManager.prototype.dispose = function () { + this.removeAll(); + }; + AssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + AssetManager.prototype.getErrors = function () { + return this.errors; + }; + return AssetManager; + }()); + spine.AssetManager = AssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AtlasAttachmentLoader = (function () { + function AtlasAttachmentLoader(atlas) { + this.atlas = atlas; + } + AtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.RegionAttachment(name); + attachment.setRegion(region); + return attachment; + }; + AtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.MeshAttachment(name); + attachment.region = region; + return attachment; + }; + AtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) { + return new spine.BoundingBoxAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { + return new spine.PathAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { + return new spine.PointAttachment(name); + }; + AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) { + return new spine.ClippingAttachment(name); + }; + return AtlasAttachmentLoader; + }()); + spine.AtlasAttachmentLoader = AtlasAttachmentLoader; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BlendMode; + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(BlendMode = spine.BlendMode || (spine.BlendMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + var skeleton = this.skeleton; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (skeleton.flipY) { + y = -y; + lc = -lc; + ld = -ld; + } + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + this.worldX = x + skeleton.x; + this.worldY = y + skeleton.y; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case spine.TransformMode.Normal: { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case spine.TransformMode.OnlyTranslation: { + var rotationY = rotation + 90 + shearY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case spine.TransformMode.NoRotationOrReflection: { + var s = pa * pa + pc * pc; + var prx = 0; + if (s > 0.0001) { + s = Math.abs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; + } + else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; + } + var rx = rotation + shearX - prx; + var ry = rotation + shearY - prx + 90; + var la = spine.MathUtils.cosDeg(rx) * scaleX; + var lb = spine.MathUtils.cosDeg(ry) * scaleY; + var lc = spine.MathUtils.sinDeg(rx) * scaleX; + var ld = spine.MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: { + var cos = spine.MathUtils.cosDeg(rotation); + var sin = spine.MathUtils.sinDeg(rotation); + var za = pa * cos + pb * sin; + var zc = pc * cos + pd * sin; + var s = Math.sqrt(za * za + zc * zc); + if (s > 0.00001) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + var r = Math.PI / 2 + Math.atan2(zc, za); + var zb = Math.cos(r) * s; + var zd = Math.sin(r) * s; + var la = spine.MathUtils.cosDeg(shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; + var lc = spine.MathUtils.sinDeg(shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { + zb = -zb; + zd = -zd; + } + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + return; + } + } + if (this.skeleton.flipX) { + this.a = -this.a; + this.b = -this.b; + } + if (this.skeleton.flipY) { + this.c = -this.c; + this.d = -this.d; + } + }; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + }; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.c * this.c); + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.b * this.b + this.d * this.d); + }; + Bone.prototype.updateAppliedTransform = function () { + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + this.ax = this.worldX; + this.ay = this.worldY; + this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = (dx * pd * pid - dy * pb * pid); + this.ay = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + } + else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; + } + }; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; + }; + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + }; + Bone.prototype.worldToLocalRotation = function (worldRotation) { + var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg; + }; + Bone.prototype.localToWorldRotation = function (localRotation) { + var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; + return Bone; + }()); + spine.Bone = Bone; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoneData = (function () { + function BoneData(index, name, parent) { + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + return BoneData; + }()); + spine.BoneData = BoneData; + var TransformMode; + (function (TransformMode) { + TransformMode[TransformMode["Normal"] = 0] = "Normal"; + TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; + TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(TransformMode = spine.TransformMode || (spine.TransformMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; +})(spine || (spine = {})); +var spine; +(function (spine) { + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.mix = 1; + this.bendDirection = 0; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.bendDirection = data.bendDirection; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + IkConstraint.prototype.getOrder = function () { + return this.data.order; + }; + IkConstraint.prototype.apply = function () { + this.update(); + }; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); + break; + } + }; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) { + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var p = bone.parent; + var id = 1 / (p.a * p.d - p.b * p.c); + var x = targetX - p.worldX, y = targetY - p.worldY; + var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; + var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); + }; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + if (!parent.appliedValid) + parent.updateAppliedTransform(); + if (!child.appliedValid) + child.updateAppliedTransform(); + var px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } + else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } + else + os2 = 0; + var cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + var u = Math.abs(psx - psy) <= 0.0001; + if (!u) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } + else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + var pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + var id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; + var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + x = cwx - pp.worldX; + y = cwy - pp.worldY; + var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1 = 0, a2 = 0; + outer: if (u) { + l2 *= psx; + var cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + cos = -1; + else if (cos > 1) + cos = 1; + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } + else { + a = psx * l2; + b = psy * l2; + var aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + var c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + var q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) / 2; + var r0 = q / c2, r1 = c / q; + var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + var os = Math.atan2(cy, cx) * s2; + var rotation = parent.arotation; + a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * spine.MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + }; + return IkConstraint; + }()); + spine.IkConstraint = IkConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraintData = (function () { + function IkConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.bendDirection = 1; + this.mix = 1; + this.name = name; + } + return IkConstraintData; + }()); + spine.IkConstraintData = IkConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraint = (function () { + function PathConstraint(data, skeleton) { + this.position = 0; + this.spacing = 0; + this.rotateMix = 0; + this.translateMix = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + } + PathConstraint.prototype.apply = function () { + this.update(); + }; + PathConstraint.prototype.update = function () { + var attachment = this.target.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + return; + var rotateMix = this.rotateMix, translateMix = this.translateMix; + var translate = translateMix > 0, rotate = rotateMix > 0; + if (!translate && !rotate) + return; + var data = this.data; + var spacingMode = data.spacingMode; + var lengthSpacing = spacingMode == spine.SpacingMode.Length; + var rotateMode = data.rotateMode; + var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale; + var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + var bones = this.bones; + var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null; + var spacing = this.spacing; + if (scale || lengthSpacing) { + if (scale) + lengths = spine.Utils.setArraySize(this.lengths, boneCount); + for (var i = 0, n = spacesCount - 1; i < n;) { + var bone = bones[i]; + var setupLength = bone.data.length; + if (setupLength < PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = 0; + } + else { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_1 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_1; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_1 / setupLength; + } + } + } + else { + for (var i = 1; i < spacesCount; i++) + spaces[i] = spacing; + } + var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, spacingMode == spine.SpacingMode.Percent); + var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + var tip = false; + if (offsetRotation == 0) + tip = rotateMode == spine.RotateMode.Chain; + else { + tip = false; + var p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + } + for (var i = 0, p = 3; i < boneCount; i++, p += 3) { + var bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; + var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + var length_2 = lengths[i]; + if (length_2 != 0) { + var s = (Math.sqrt(dx * dx + dy * dy) / length_2 - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (rotate) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + var length_3 = bone.data.length; + boneX += (length_3 * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length_3 * (sin * a + cos * c) - dy) * rotateMix; + } + else { + r += offsetRotation; + } + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.appliedValid = false; + } + }; + PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) { + var target = this.target; + var position = this.position; + var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + var closed = path.closed; + var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; + if (!path.constantSpeed) { + var lengths = path.lengths; + curveCount -= closed ? 1 : 2; + var pathLength_1 = lengths[curveCount]; + if (percentPosition) + position *= pathLength_1; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength_1; + } + world = spine.Utils.setArraySize(this.world, 8); + for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength_1; + if (p < 0) + p += pathLength_1; + curve = 0; + } + else if (p < 0) { + if (prevCurve != PathConstraint.BEFORE) { + prevCurve = PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength_1) { + if (prevCurve != PathConstraint.AFTER) { + prevCurve = PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength_1, world, 0, out, o); + continue; + } + for (;; curve++) { + var length_4 = lengths[curve]; + if (p > length_4) + continue; + if (curve == 0) + p /= length_4; + else { + var prev = lengths[curve - 1]; + p = (p - prev) / (length_4 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } + else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); + } + return out; + } + if (closed) { + verticesLength += 2; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else { + curveCount--; + verticesLength -= 4; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + var curves = spine.Utils.setArraySize(this.curves, curveCount); + var pathLength = 0; + var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (var i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (percentPosition) + position *= pathLength; + if (percentSpacing) { + for (var i = 0; i < spacesCount; i++) + spaces[i] *= pathLength; + } + var segments = this.segments; + var curveLength = 0; + for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } + else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (;; curve++) { + var length_5 = curves[curve]; + if (p > length_5) + continue; + if (curve == 0) + p /= length_5; + else { + var prev = curves[curve - 1]; + p = (p - prev) / (length_5 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + var ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (;; segment++) { + var length_6 = segments[segment]; + if (p > length_6) + continue; + if (segment == 0) + p /= length_6; + else { + var prev = segments[segment - 1]; + p = segment + (p - prev) / (length_6 - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + } + return out; + }; + PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) { + var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) { + var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) + p = 0.0001; + var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + }; + PathConstraint.prototype.getOrder = function () { + return this.data.order; + }; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + PathConstraint.epsilon = 0.00001; + return PathConstraint; + }()); + spine.PathConstraint = PathConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraintData = (function () { + function PathConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.name = name; + } + return PathConstraintData; + }()); + spine.PathConstraintData = PathConstraintData; + var PositionMode; + (function (PositionMode) { + PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; + PositionMode[PositionMode["Percent"] = 1] = "Percent"; + })(PositionMode = spine.PositionMode || (spine.PositionMode = {})); + var SpacingMode; + (function (SpacingMode) { + SpacingMode[SpacingMode["Length"] = 0] = "Length"; + SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; + SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; + })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {})); + var RotateMode; + (function (RotateMode) { + RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; + RotateMode[RotateMode["Chain"] = 1] = "Chain"; + RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; + })(RotateMode = spine.RotateMode || (spine.RotateMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Assets = (function () { + function Assets(clientId) { + this.toLoad = new Array(); + this.assets = {}; + this.clientId = clientId; + } + Assets.prototype.loaded = function () { + var i = 0; + for (var v in this.assets) + i++; + return i; + }; + return Assets; + }()); + var SharedAssetManager = (function () { + function SharedAssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.clientAssets = {}; + this.queuedAssets = {}; + this.rawAssets = {}; + this.errors = {}; + this.pathPrefix = pathPrefix; + } + SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) { + clientAssets = new Assets(clientId); + this.clientAssets[clientId] = clientAssets; + } + if (textureLoader !== null) + clientAssets.textureLoader = textureLoader; + clientAssets.toLoad.push(path); + if (this.queuedAssets[path] === path) { + return false; + } + else { + this.queuedAssets[path] = path; + return true; + } + }; + SharedAssetManager.prototype.loadText = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = request.responseText; + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadJson = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = JSON.parse(request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, textureLoader, path)) + return; + var img = new Image(); + img.src = path; + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + _this.rawAssets[path] = img; + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + }; + }; + SharedAssetManager.prototype.get = function (clientId, path) { + path = this.pathPrefix + path; + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + return clientAssets.assets[path]; + }; + SharedAssetManager.prototype.updateClientAssets = function (clientAssets) { + for (var i = 0; i < clientAssets.toLoad.length; i++) { + var path = clientAssets.toLoad[i]; + var asset = clientAssets.assets[path]; + if (asset === null || asset === undefined) { + var rawAsset = this.rawAssets[path]; + if (rawAsset === null || rawAsset === undefined) + continue; + if (rawAsset instanceof HTMLImageElement) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + } + }; + SharedAssetManager.prototype.isLoadingComplete = function (clientId) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + this.updateClientAssets(clientAssets); + return clientAssets.toLoad.length == clientAssets.loaded(); + }; + SharedAssetManager.prototype.dispose = function () { + }; + SharedAssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + SharedAssetManager.prototype.getErrors = function () { + return this.errors; + }; + return SharedAssetManager; + }()); + spine.SharedAssetManager = SharedAssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skeleton = (function () { + function Skeleton(data) { + this._updateCache = new Array(); + this.updateCacheReset = new Array(); + this.time = 0; + this.flipX = false; + this.flipY = false; + this.x = 0; + this.y = 0; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) { + var boneData = data.bones[i]; + var bone = void 0; + if (boneData.parent == null) + bone = new spine.Bone(boneData, this, null); + else { + var parent_1 = this.bones[boneData.parent.index]; + bone = new spine.Bone(boneData, this, parent_1); + parent_1.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (var i = 0; i < data.slots.length; i++) { + var slotData = data.slots[i]; + var bone = this.bones[slotData.boneData.index]; + var slot = new spine.Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (var i = 0; i < data.ikConstraints.length; i++) { + var ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (var i = 0; i < data.transformConstraints.length; i++) { + var transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (var i = 0; i < data.pathConstraints.length; i++) { + var pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this)); + } + this.color = new spine.Color(1, 1, 1, 1); + this.updateCache(); + } + Skeleton.prototype.updateCache = function () { + var updateCache = this._updateCache; + updateCache.length = 0; + this.updateCacheReset.length = 0; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].sorted = false; + var ikConstraints = this.ikConstraints; + var transformConstraints = this.transformConstraints; + var pathConstraints = this.pathConstraints; + var ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + var constraintCount = ikCount + transformCount + pathCount; + outer: for (var i = 0; i < constraintCount; i++) { + for (var ii = 0; ii < ikCount; ii++) { + var constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < transformCount; ii++) { + var constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < pathCount; ii++) { + var constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (var i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + }; + Skeleton.prototype.sortIkConstraint = function (constraint) { + var target = constraint.target; + this.sortBone(target); + var constrained = constraint.bones; + var parent = constrained[0]; + this.sortBone(parent); + if (constrained.length > 1) { + var child = constrained[constrained.length - 1]; + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + this._updateCache.push(constraint); + this.sortReset(parent.children); + constrained[constrained.length - 1].sorted = true; + }; + Skeleton.prototype.sortPathConstraint = function (constraint) { + var slot = constraint.target; + var slotIndex = slot.data.index; + var slotBone = slot.bone; + if (this.skin != null) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (var i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + var attachment = slot.getAttachment(); + if (attachment instanceof spine.PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (var i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (var i = 0; i < boneCount; i++) + constrained[i].sorted = true; + }; + Skeleton.prototype.sortTransformConstraint = function (constraint) { + this.sortBone(constraint.target); + var constrained = constraint.bones; + var boneCount = constrained.length; + if (constraint.data.local) { + for (var i = 0; i < boneCount; i++) { + var child = constrained[i]; + this.sortBone(child.parent); + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + } + else { + for (var i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + }; + Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) { + var attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (var key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + }; + Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) { + if (!(attachment instanceof spine.PathAttachment)) + return; + var pathBones = attachment.bones; + if (pathBones == null) + this.sortBone(slotBone); + else { + var bones = this.bones; + var i = 0; + while (i < pathBones.length) { + var boneCount = pathBones[i++]; + for (var n = i + boneCount; i < n; i++) { + var boneIndex = pathBones[i]; + this.sortBone(bones[boneIndex]); + } + } + } + }; + Skeleton.prototype.sortBone = function (bone) { + if (bone.sorted) + return; + var parent = bone.parent; + if (parent != null) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + }; + Skeleton.prototype.sortReset = function (bones) { + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + }; + Skeleton.prototype.updateWorldTransform = function () { + var updateCacheReset = this.updateCacheReset; + for (var i = 0, n = updateCacheReset.length; i < n; i++) { + var bone = updateCacheReset[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + var updateCache = this._updateCache; + for (var i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + }; + Skeleton.prototype.setToSetupPose = function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }; + Skeleton.prototype.setBonesToSetupPose = function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + constraint.bendDirection = constraint.data.bendDirection; + constraint.mix = constraint.data.mix; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + } + }; + Skeleton.prototype.setSlotsToSetupPose = function () { + var slots = this.slots; + spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + }; + Skeleton.prototype.getRootBone = function () { + if (this.bones.length == 0) + return null; + return this.bones[0]; + }; + Skeleton.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + }; + Skeleton.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) + return i; + return -1; + }; + Skeleton.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + }; + Skeleton.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) + return i; + return -1; + }; + Skeleton.prototype.setSkinByName = function (skinName) { + var skin = this.data.findSkin(skinName); + if (skin == null) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + }; + Skeleton.prototype.setSkin = function (newSkin) { + if (newSkin != null) { + if (this.skin != null) + newSkin.attachAll(this, this.skin); + else { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var name_1 = slot.data.attachmentName; + if (name_1 != null) { + var attachment = newSkin.getAttachment(i, name_1); + if (attachment != null) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + }; + Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) { + return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName); + }; + Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) { + if (attachmentName == null) + throw new Error("attachmentName cannot be null."); + if (this.skin != null) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + return attachment; + } + if (this.data.defaultSkin != null) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }; + Skeleton.prototype.setAttachment = function (slotName, attachmentName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName != null) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + }; + Skeleton.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + }; + Skeleton.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.getBounds = function (offset, size, temp) { + if (offset == null) + throw new Error("offset cannot be null."); + if (size == null) + throw new Error("size cannot be null."); + var drawOrder = this.drawOrder; + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var verticesLength = 0; + var vertices = null; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) { + verticesLength = 8; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices != null) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { + var x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + }; + Skeleton.prototype.update = function (delta) { + this.time += delta; + }; + return Skeleton; + }()); + spine.Skeleton = Skeleton; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBounds = (function () { + function SkeletonBounds() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new spine.Pool(function () { + return spine.Utils.newFloatArray(16); + }); + } + SkeletonBounds.prototype.update = function (skeleton, updateAabb) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + var boundingBoxes = this.boundingBoxes; + var polygons = this.polygons; + var polygonPool = this.polygonPool; + var slots = skeleton.slots; + var slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (var i = 0; i < slotCount; i++) { + var slot = slots[i]; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.BoundingBoxAttachment) { + var boundingBox = attachment; + boundingBoxes.push(boundingBox); + var polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } + else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + }; + SkeletonBounds.prototype.aabbCompute = function () { + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + var vertices = polygon; + for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) { + var x = vertices[ii]; + var y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + }; + SkeletonBounds.prototype.aabbContainsPoint = function (x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + }; + SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) { + var minX = this.minX; + var minY = this.minY; + var maxX = this.maxX; + var maxY = this.maxY; + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + return false; + var m = (y2 - y1) / (x2 - x1); + var y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + var x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + }; + SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + }; + SkeletonBounds.prototype.containsPoint = function (x, y) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) { + var vertices = polygon; + var nn = polygon.length; + var prevIndex = nn - 2; + var inside = false; + for (var ii = 0; ii < nn; ii += 2) { + var vertexY = vertices[ii + 1]; + var prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + var vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + }; + SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) { + var vertices = polygon; + var nn = polygon.length; + var width12 = x1 - x2, height12 = y1 - y2; + var det1 = x1 * y2 - y1 * x2; + var x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (var ii = 0; ii < nn; ii += 2) { + var x4 = vertices[ii], y4 = vertices[ii + 1]; + var det2 = x3 * y4 - y3 * x4; + var width34 = x3 - x4, height34 = y3 - y4; + var det3 = width12 * height34 - height12 * width34; + var x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + var y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + }; + SkeletonBounds.prototype.getPolygon = function (boundingBox) { + if (boundingBox == null) + throw new Error("boundingBox cannot be null."); + var index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + }; + SkeletonBounds.prototype.getWidth = function () { + return this.maxX - this.minX; + }; + SkeletonBounds.prototype.getHeight = function () { + return this.maxY - this.minY; + }; + return SkeletonBounds; + }()); + spine.SkeletonBounds = SkeletonBounds; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonClipping = (function () { + function SkeletonClipping() { + this.triangulator = new spine.Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + SkeletonClipping.prototype.clipStart = function (slot, clip) { + if (this.clipAttachment != null) + return 0; + this.clipAttachment = clip; + var n = clip.worldVerticesLength; + var vertices = spine.Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + var clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) { + var polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + }; + SkeletonClipping.prototype.clipEndWithSlot = function (slot) { + if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + }; + SkeletonClipping.prototype.clipEnd = function () { + if (this.clipAttachment == null) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + }; + SkeletonClipping.prototype.isClipping = function () { + return this.clipAttachment != null; + }; + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + var clippedTriangles = this.clippedTriangles; + var polygons = this.clippingPolygons; + var polygonsCount = this.clippingPolygons.length; + var vertexSize = twoColor ? 12 : 8; + var index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: for (var i = 0; i < trianglesLength; i += 3) { + var vertexOffset = triangles[i] << 1; + var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { + var s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + var clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + var d = 1 / (d0 * d2 + d1 * (y1 - y3)); + var clipOutputCount = clipOutputLength >> 1; + var clipOutputItems = this.clipOutput; + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (var ii = 0; ii < clipOutputLength; ii += 2) { + var x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + var c0 = x - x3, c1 = y - y3; + var a = (d0 * c0 + d1 * c1) * d; + var b = (d4 * c0 + d2 * c1) * d; + var c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (var ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + ii); + clippedTrianglesItems[s + 2] = (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } + else { + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } + else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + 1); + clippedTrianglesItems[s + 2] = (index + 2); + index += 3; + continue outer; + } + } + } + }; + SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) { + var originalOutput = output; + var clipped = false; + var input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } + else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + var clippingVertices = clippingArea; + var clippingVerticesLast = clippingArea.length - 4; + for (var i = 0;; i += 2) { + var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + var inputVertices = input; + var inputVerticesLength = input.length - 2, outputStart = output.length; + for (var ii = 0; ii < inputVerticesLength; ii += 2) { + var inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else if (side2) { + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + var temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (var i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } + else + originalOutput.length = originalOutput.length - 2; + return clipped; + }; + SkeletonClipping.makeClockwise = function (polygon) { + var vertices = polygon; + var verticeslength = polygon.length; + var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (var i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + var x = vertices[i], y = vertices[i + 1]; + var other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + }; + return SkeletonClipping; + }()); + spine.SkeletonClipping = SkeletonClipping; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonData = (function () { + function SkeletonData() { + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + this.fps = 0; + } + SkeletonData.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + }; + SkeletonData.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) + return i; + return -1; + }; + SkeletonData.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + }; + SkeletonData.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) + return i; + return -1; + }; + SkeletonData.prototype.findSkin = function (skinName) { + if (skinName == null) + throw new Error("skinName cannot be null."); + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) { + var skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + }; + SkeletonData.prototype.findEvent = function (eventDataName) { + if (eventDataName == null) + throw new Error("eventDataName cannot be null."); + var events = this.events; + for (var i = 0, n = events.length; i < n; i++) { + var event_4 = events[i]; + if (event_4.name == eventDataName) + return event_4; + } + return null; + }; + SkeletonData.prototype.findAnimation = function (animationName) { + if (animationName == null) + throw new Error("animationName cannot be null."); + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) { + var animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + }; + SkeletonData.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) { + if (pathConstraintName == null) + throw new Error("pathConstraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) + if (pathConstraints[i].name == pathConstraintName) + return i; + return -1; + }; + return SkeletonData; + }()); + spine.SkeletonData = SkeletonData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonJson = (function () { + function SkeletonJson(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonJson.prototype.readSkeletonData = function (json) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + var root = typeof (json) === "string" ? JSON.parse(json) : json; + var skeletonMap = root.skeleton; + if (skeletonMap != null) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (var i = 0; i < root.bones.length; i++) { + var boneMap = root.bones[i]; + var parent_2 = null; + var parentName = this.getValue(boneMap, "parent", null); + if (parentName != null) { + parent_2 = skeletonData.findBone(parentName); + if (parent_2 == null) + throw new Error("Parent bone not found: " + parentName); + } + var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_2); + data.length = this.getValue(boneMap, "length", 0) * scale; + data.x = this.getValue(boneMap, "x", 0) * scale; + data.y = this.getValue(boneMap, "y", 0) * scale; + data.rotation = this.getValue(boneMap, "rotation", 0); + data.scaleX = this.getValue(boneMap, "scaleX", 1); + data.scaleY = this.getValue(boneMap, "scaleY", 1); + data.shearX = this.getValue(boneMap, "shearX", 0); + data.shearY = this.getValue(boneMap, "shearY", 0); + data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, "transform", "normal")); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (var i = 0; i < root.slots.length; i++) { + var slotMap = root.slots[i]; + var slotName = slotMap.name; + var boneName = slotMap.bone; + var boneData = skeletonData.findBone(boneName); + if (boneData == null) + throw new Error("Slot bone not found: " + boneName); + var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData); + var color = this.getValue(slotMap, "color", null); + if (color != null) + data.color.setFromString(color); + var dark = this.getValue(slotMap, "dark", null); + if (dark != null) { + data.darkColor = new spine.Color(1, 1, 1, 1); + data.darkColor.setFromString(dark); + } + data.attachmentName = this.getValue(slotMap, "attachment", null); + data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (var i = 0; i < root.ik.length; i++) { + var constraintMap = root.ik[i]; + var data = new spine.IkConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("IK bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("IK target bone not found: " + targetName); + data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.mix = this.getValue(constraintMap, "mix", 1); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (var i = 0; i < root.transform.length; i++) { + var constraintMap = root.transform[i]; + var data = new spine.TransformConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("Transform constraint target bone not found: " + targetName); + data.local = this.getValue(constraintMap, "local", false); + data.relative = this.getValue(constraintMap, "relative", false); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.offsetX = this.getValue(constraintMap, "x", 0) * scale; + data.offsetY = this.getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0); + data.offsetShearY = this.getValue(constraintMap, "shearY", 0); + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + data.scaleMix = this.getValue(constraintMap, "scaleMix", 1); + data.shearMix = this.getValue(constraintMap, "shearMix", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (var i = 0; i < root.path.length; i++) { + var constraintMap = root.path[i]; + var data = new spine.PathConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + if (data.target == null) + throw new Error("Path target slot not found: " + targetName); + data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent")); + data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length")); + data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent")); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.position = this.getValue(constraintMap, "position", 0); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = this.getValue(constraintMap, "spacing", 0); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (var skinName in root.skins) { + var skinMap = root.skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + var slotMap = skinMap[slotName]; + for (var entryName in slotMap) { + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData); + if (attachment != null) + skin.addAttachment(slotIndex, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (var i = 0, n = this.linkedMeshes.length; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_3 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_3 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.setParentMesh(parent_3); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (var eventName in root.events) { + var eventMap = root.events[eventName]; + var data = new spine.EventData(eventName); + data.intValue = this.getValue(eventMap, "int", 0); + data.floatValue = this.getValue(eventMap, "float", 0); + data.stringValue = this.getValue(eventMap, "string", ""); + skeletonData.events.push(data); + } + } + if (root.animations) { + for (var animationName in root.animations) { + var animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + }; + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) { + var scale = this.scale; + name = this.getValue(map, "name", name); + var type = this.getValue(map, "type", "region"); + switch (type) { + case "region": { + var path = this.getValue(map, "path", name); + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = this.getValue(map, "x", 0) * scale; + region.y = this.getValue(map, "y", 0) * scale; + region.scaleX = this.getValue(map, "scaleX", 1); + region.scaleY = this.getValue(map, "scaleY", 1); + region.rotation = this.getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + var color = this.getValue(map, "color", null); + if (color != null) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + this.readVertices(map, box, map.vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + var path = this.getValue(map, "path", name); + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + var color = this.getValue(map, "color", null); + if (color != null) + mesh.color.setFromString(color); + var parent_4 = this.getValue(map, "parent", null); + if (parent_4 != null) { + mesh.inheritDeform = this.getValue(map, "deform", true); + this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_4)); + return mesh; + } + var uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = this.getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = this.getValue(map, "closed", false); + path.constantSpeed = this.getValue(map, "constantSpeed", true); + var vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + var color = this.getValue(map, "color", null); + if (color != null) + path.color.setFromString(color); + return path; + } + case "point": { + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = this.getValue(map, "x", 0) * scale; + point.y = this.getValue(map, "y", 0) * scale; + point.rotation = this.getValue(map, "rotation", 0); + var color = this.getValue(map, "color", null); + if (color != null) + point.color.setFromString(color); + return point; + } + case "clipping": { + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + var end = this.getValue(map, "end", null); + if (end != null) { + var slot = skeletonData.findSlot(end); + if (slot == null) + throw new Error("Clipping end slot not found: " + end); + clip.endSlot = slot; + } + var vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + clip.color.setFromString(color); + return clip; + } + } + return null; + }; + SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) { + var scale = this.scale; + attachment.worldVerticesLength = verticesLength; + var vertices = map.vertices; + if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); + if (scale != 1) { + for (var i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + var weights = new Array(); + var bones = new Array(); + for (var i = 0, n = vertices.length; i < n;) { + var boneCount = vertices[i++]; + bones.push(boneCount); + for (var nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = spine.Utils.toFloatArray(weights); + }; + SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) { + var scale = this.scale; + var timelines = new Array(); + var duration = 0; + if (map.slots) { + for (var slotName in map.slots) { + var slotMap = map.slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else if (timelineName == "color") { + var timeline = new spine.ColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var color = new spine.Color(); + color.setFromString(valueMap.color); + timeline.setFrame(frameIndex, valueMap.time, color.r, color.g, color.b, color.a); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); + } + else if (timelineName == "twoColor") { + var timeline = new spine.TwoColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var light = new spine.Color(); + var dark = new spine.Color(); + light.setFromString(valueMap.light); + dark.setFromString(valueMap.dark); + timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + if (map.bones) { + for (var boneName in map.bones) { + var boneMap = map.bones[boneName]; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) + throw new Error("Bone not found: " + boneName); + for (var timelineName in boneMap) { + var timelineMap = boneMap[timelineName]; + if (timelineName === "rotate") { + var timeline = new spine.RotateTimeline(timelineMap.length); + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, valueMap.angle); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]); + } + else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "scale") + timeline = new spine.ScaleTimeline(timelineMap.length); + else if (timelineName === "shear") + timeline = new spine.ShearTimeline(timelineMap.length); + else { + timeline = new spine.TranslateTimeline(timelineMap.length); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var x = this.getValue(valueMap, "x", 0), y = this.getValue(valueMap, "y", 0); + timeline.setFrame(frameIndex, valueMap.time, x * timelineScale, y * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); + } + } + } + if (map.ik) { + for (var constraintName in map.ik) { + var constraintMap = map.ik[constraintName]; + var constraint = skeletonData.findIkConstraint(constraintName); + var timeline = new spine.IkConstraintTimeline(constraintMap.length); + timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + } + if (map.transform) { + for (var constraintName in map.transform) { + var constraintMap = map.transform[constraintName]; + var constraint = skeletonData.findTransformConstraint(constraintName); + var timeline = new spine.TransformConstraintTimeline(constraintMap.length); + timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + } + if (map.paths) { + for (var constraintName in map.paths) { + var constraintMap = map.paths[constraintName]; + var index = skeletonData.findPathConstraintIndex(constraintName); + if (index == -1) + throw new Error("Path constraint not found: " + constraintName); + var data = skeletonData.pathConstraints[index]; + for (var timelineName in constraintMap) { + var timelineMap = constraintMap[timelineName]; + if (timelineName === "position" || timelineName === "spacing") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "spacing") { + timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(timelineMap.length); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, timelineName, 0) * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + } + else if (timelineName === "mix") { + var timeline = new spine.PathConstraintMixTimeline(timelineMap.length); + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + } + } + } + } + if (map.deform) { + for (var deformName in map.deform) { + var deformMap = map.deform[deformName]; + var skin = skeletonData.findSkin(deformName); + if (skin == null) + throw new Error("Skin not found: " + deformName); + for (var slotName in deformMap) { + var slotMap = deformMap[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotMap.name); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + var attachment = skin.getAttachment(slotIndex, timelineName); + if (attachment == null) + throw new Error("Deform attachment not found: " + timelineMap.name); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var timeline = new spine.DeformTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + var frameIndex = 0; + for (var j = 0; j < timelineMap.length; j++) { + var valueMap = timelineMap[j]; + var deform = void 0; + var verticesValue = this.getValue(valueMap, "vertices", null); + if (verticesValue == null) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = this.getValue(valueMap, "offset", 0); + spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (var i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (var i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frameIndex, valueMap.time, deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_5 = new spine.Event(spine.Utils.toSinglePrecision(eventMap.time), eventData); + event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + timeline.setFrame(frameIndex++, event_5); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.curve) + return; + if (map.curve === "stepped") + timeline.setStepped(frameIndex); + else if (Object.prototype.toString.call(map.curve) === '[object Array]') { + var curve = map.curve; + timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + SkeletonJson.transformModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.TransformMode.Normal; + if (str == "onlytranslation") + return spine.TransformMode.OnlyTranslation; + if (str == "norotationorreflection") + return spine.TransformMode.NoRotationOrReflection; + if (str == "noscale") + return spine.TransformMode.NoScale; + if (str == "noscaleorreflection") + return spine.TransformMode.NoScaleOrReflection; + throw new Error("Unknown transform mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.addAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.attachmentVertices = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.darkColor = data.darkColor == null ? null : new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.attachmentVertices.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.darkColor != null) + this.darkColor.setFromColor(this.data.darkColor); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + var TextureFilter; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {})); + var TextureWrap; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {})); + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; + var FakeTexture = (function (_super) { + __extends(FakeTexture, _super); + function FakeTexture() { + return _super !== null && _super.apply(this, arguments) || this; + } + FakeTexture.prototype.setFilters = function (minFilter, magFilter) { }; + FakeTexture.prototype.setWraps = function (uWrap, vWrap) { }; + FakeTexture.prototype.dispose = function () { }; + return FakeTexture; + }(spine.Texture)); + spine.FakeTexture = FakeTexture; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + region.rotate = reader.readValue() == "true"; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + return _super !== null && _super.apply(this, arguments) || this; + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } + else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + }; + TransformConstraint.prototype.applyAbsoluteWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect; + var offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; + bone.a *= s; + bone.c *= s; + s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyRelativeWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * translateMix; + bone.worldY += temp.y * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + var b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyAbsoluteLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) { + var r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + var shearY = bone.ashearY; + if (shearMix > 0) { + var r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.applyRelativeLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) + rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) + scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + var shearY = bone.ashearY; + if (shearMix > 0) + shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.getOrder = function () { + return this.data.order; + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function () { + function TransformConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + this.relative = false; + this.local = false; + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return TransformConstraintData; + }()); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Triangulator = (function () { + function Triangulator() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new spine.Pool(function () { + return new Array(); + }); + this.polygonIndicesPool = new spine.Pool(function () { + return new Array(); + }); + } + Triangulator.prototype.triangulate = function (verticesArray) { + var vertices = verticesArray; + var vertexCount = verticesArray.length >> 1; + var indices = this.indicesArray; + indices.length = 0; + for (var i = 0; i < vertexCount; i++) + indices[i] = i; + var isConcave = this.isConcaveArray; + isConcave.length = 0; + for (var i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + var triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + var previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: if (!isConcave[i]) { + var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + var p1x = vertices[p1], p1y = vertices[p1 + 1]; + var p2x = vertices[p2], p2y = vertices[p2 + 1]; + var p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + var v = indices[ii] << 1; + var vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + var previousIndex = (vertexCount + i - 1) % vertexCount; + var nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + }; + Triangulator.prototype.decompose = function (verticesArray, triangles) { + var vertices = verticesArray; + var convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + var convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + var polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + var polygon = this.polygonPool.obtain(); + polygon.length = 0; + var fanBaseIndex = -1, lastWinding = 0; + for (var i = 0, n = triangles.length; i < n; i += 3) { + var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + var x1 = vertices[t1], y1 = vertices[t1 + 1]; + var x2 = vertices[t2], y2 = vertices[t2 + 1]; + var x3 = vertices[t3], y3 = vertices[t3 + 1]; + var merged = false; + if (fanBaseIndex == t1) { + var o = polygon.length - 4; + var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (var i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + var firstIndex = polygonIndices[0]; + var lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + var o = polygon.length - 4; + var prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + var prevX = polygon[o + 2], prevY = polygon[o + 3]; + var firstX = polygon[0], firstY = polygon[1]; + var secondX = polygon[2], secondY = polygon[3]; + var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (var ii = 0; ii < n; ii++) { + if (ii == i) + continue; + var otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + var otherFirstIndex = otherIndices[0]; + var otherSecondIndex = otherIndices[1]; + var otherLastIndex = otherIndices[2]; + var otherPoly = convexPolygons[ii]; + var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (var i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + }; + Triangulator.isConcave = function (index, vertexCount, vertices, indices) { + var previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + var current = indices[index] << 1; + var next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); + }; + Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + }; + Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) { + var px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + }; + return Triangulator; + }()); + spine.Triangulator = Triangulator; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IntSet = (function () { + function IntSet() { + this.array = new Array(); + } + IntSet.prototype.add = function (value) { + var contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + }; + IntSet.prototype.contains = function (value) { + return this.array[value | 0] != undefined; + }; + IntSet.prototype.remove = function (value) { + this.array[value | 0] = undefined; + }; + IntSet.prototype.clear = function () { + this.array.length = 0; + }; + return IntSet; + }()); + spine.IntSet = IntSet; + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + }; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + }; + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + }; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; + }()); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { + } + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); + }; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); + }; + MathUtils.signum = function (value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + }; + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + }; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + }; + MathUtils.randomTriangular = function (min, max) { + return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + }; + MathUtils.randomTriangularWith = function (min, max, mode) { + var u = Math.random(); + var d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + }; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; + }()); + spine.MathUtils = MathUtils; + var Interpolation = (function () { + function Interpolation() { + } + Interpolation.prototype.apply = function (start, end, a) { + return start + (end - start) * this.applyInternal(a); + }; + return Interpolation; + }()); + spine.Interpolation = Interpolation; + var Pow = (function (_super) { + __extends(Pow, _super); + function Pow(power) { + var _this = _super.call(this) || this; + _this.power = 2; + _this.power = power; + return _this; + } + Pow.prototype.applyInternal = function (a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + }; + return Pow; + }(Interpolation)); + spine.Pow = Pow; + var PowOut = (function (_super) { + __extends(PowOut, _super); + function PowOut(power) { + return _super.call(this, power) || this; + } + PowOut.prototype.applyInternal = function (a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + }; + return PowOut; + }(Pow)); + spine.PowOut = PowOut; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; + } + return array; + }; + Utils.ensureArrayCapacity = function (array, size, value) { + if (value === void 0) { value = 0; } + if (array.length >= size) + return array; + return Utils.setArraySize(array, size, value); + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.newShortArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Int16Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.toSinglePrecision = function (value) { + return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + }; + Utils.webkit602BugfixHelper = function (alpha, pose) { + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; + }()); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { + } + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + }; + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + }; + Pool.prototype.free = function (item) { + if (item.reset) + item.reset(); + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) { + if (items[i].reset) + items[i].reset(); + this.items[i] = items[i]; + } + }; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; + }()); + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; + } + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; + }()); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; + } + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + }; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; + var WindowedMean = (function () { + function WindowedMean(windowSize) { + if (windowSize === void 0) { windowSize = 32; } + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + WindowedMean.prototype.hasEnoughData = function () { + return this.addedValues >= this.values.length; + }; + WindowedMean.prototype.addValue = function (value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + }; + WindowedMean.prototype.getMean = function () { + if (this.hasEnoughData()) { + if (this.dirty) { + var mean = 0; + for (var i = 0; i < this.values.length; i++) { + mean += this.values[i]; + } + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + else { + return 0; + } + }; + return WindowedMean; + }()); + spine.WindowedMean = WindowedMean; +})(spine || (spine = {})); +(function () { + if (!Math.fround) { + Math.fround = (function (array) { + return function (x) { + return array[0] = x, array[0]; + }; + })(new Float32Array(1)); + } +})(); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + var _this = _super.call(this, name) || this; + _this.id = (VertexAttachment.nextID++ & 65535) << 11; + _this.worldVerticesLength = 0; + return _this; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + var skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; + }; + VertexAttachment.nextID = 0; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AttachmentType; + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + AttachmentType[AttachmentType["Point"] = 5] = "Point"; + })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var ClippingAttachment = (function (_super) { + __extends(ClippingAttachment, _super); + function ClippingAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1); + return _this; + } + return ClippingAttachment; + }(spine.VertexAttachment)); + spine.ClippingAttachment = ClippingAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + _this.inheritDeform = false; + _this.tempColor = new spine.Color(0, 0, 0, 0); + return _this; + } + MeshAttachment.prototype.updateUVs = function () { + var u = 0, v = 0, width = 0, height = 0; + if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; + } + var regionUVs = this.regionUVs; + if (this.uvs == null || this.uvs.length != regionUVs.length) + this.uvs = spine.Utils.newFloatArray(regionUVs.length); + var uvs = this.uvs; + if (this.region.rotate) { + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + height - regionUVs[i] * height; + } + } + else { + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + }; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + var _this = _super.call(this, name) || this; + _this.closed = false; + _this.constantSpeed = false; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PointAttachment = (function (_super) { + __extends(PointAttachment, _super); + function PointAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.38, 0.94, 0, 1); + return _this; + } + PointAttachment.prototype.computeWorldPosition = function (bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + }; + PointAttachment.prototype.computeWorldRotation = function (bone) { + var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation); + var x = cos * bone.a + sin * bone.b; + var y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * spine.MathUtils.radDeg; + }; + return PointAttachment; + }(spine.VertexAttachment)); + spine.PointAttachment = PointAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + var _this = _super.call(this, name) || this; + _this.x = 0; + _this.y = 0; + _this.scaleX = 1; + _this.scaleY = 1; + _this.rotation = 0; + _this.width = 0; + _this.height = 0; + _this.color = new spine.Color(1, 1, 1, 1); + _this.offset = spine.Utils.newFloatArray(8); + _this.uvs = spine.Utils.newFloatArray(8); + _this.tempColor = new spine.Color(1, 1, 1, 1); + return _this; + } + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.setRegion = function (region) { + this.region = region; + var uvs = this.uvs; + if (region.rotate) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; + } + else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + }; + RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) { + var vertexOffset = this.offset; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = vertexOffset[RegionAttachment.OX1]; + offsetY = vertexOffset[RegionAttachment.OY1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX2]; + offsetY = vertexOffset[RegionAttachment.OY2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX3]; + offsetY = vertexOffset[RegionAttachment.OY3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX4]; + offsetY = vertexOffset[RegionAttachment.OY4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + }; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var JitterEffect = (function () { + function JitterEffect(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; + } + JitterEffect.prototype.begin = function (skeleton) { + }; + JitterEffect.prototype.transform = function (position, uv, light, dark) { + position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + }; + JitterEffect.prototype.end = function () { + }; + return JitterEffect; + }()); + spine.JitterEffect = JitterEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SwirlEffect = (function () { + function SwirlEffect(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; + } + SwirlEffect.prototype.begin = function (skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + }; + SwirlEffect.prototype.transform = function (position, uv, light, dark) { + var radAngle = this.angle * spine.MathUtils.degreesToRadians; + var x = position.x - this.worldX; + var y = position.y - this.worldY; + var dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + var cos = Math.cos(theta); + var sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + }; + SwirlEffect.prototype.end = function () { + }; + SwirlEffect.interpolation = new spine.PowOut(2); + return SwirlEffect; + }()); + spine.SwirlEffect = SwirlEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + return _super.call(this, function (image) { return new spine.canvas.CanvasTexture(image); }, pathPrefix) || this; + } + return AssetManager; + }(spine.AssetManager)); + canvas.AssetManager = AssetManager; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var CanvasTexture = (function (_super) { + __extends(CanvasTexture, _super); + function CanvasTexture(image) { + return _super.call(this, image) || this; + } + CanvasTexture.prototype.setFilters = function (minFilter, magFilter) { }; + CanvasTexture.prototype.setWraps = function (uWrap, vWrap) { }; + CanvasTexture.prototype.dispose = function () { }; + return CanvasTexture; + }(spine.Texture)); + canvas.CanvasTexture = CanvasTexture; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var SkeletonRenderer = (function () { + function SkeletonRenderer(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.vertices = spine.Utils.newFloatArray(8 * 1024); + this.tempColor = new spine.Color(); + this.ctx = context; + } + SkeletonRenderer.prototype.draw = function (skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + }; + SkeletonRenderer.prototype.drawImages = function (skeleton) { + var ctx = this.ctx; + var drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + ctx.save(); + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var regionAttachment = null; + var region = null; + var image = null; + if (attachment instanceof spine.RegionAttachment) { + regionAttachment = attachment; + region = regionAttachment.region; + image = region.texture.getImage(); + } + else + continue; + var skeleton_1 = slot.bone.skeleton; + var skeletonColor = skeleton_1.color; + var slotColor = slot.color; + var regionColor = regionAttachment.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, alpha); + var att = attachment; + var bone = slot.bone; + var w = region.width; + var h = region.height; + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + var atlasScale = att.width / w; + ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); + ctx.translate(w / 2, h / 2); + if (attachment.region.rotate) { + var t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + if (color.r != 1 || color.g != 1 || color.b != 1 || color.a != 1) { + ctx.globalAlpha = color.a; + } + ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + ctx.restore(); + }; + SkeletonRenderer.prototype.drawTriangles = function (skeleton) { + var blendMode = null; + var vertices = this.vertices; + var triangles = null; + var drawOrder = skeleton.drawOrder; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var texture = null; + var region = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.texture.getImage(); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture.getImage(); + } + else + continue; + if (texture != null) { + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + } + var skeleton_2 = slot.bone.skeleton; + var skeletonColor = skeleton_2.color; + var slotColor = slot.color; + var attachmentColor = attachment.color; + var alpha = skeletonColor.a * slotColor.a * attachmentColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha); + var ctx = this.ctx; + if (color.r != 1 || color.g != 1 || color.b != 1 || color.a != 1) { + ctx.globalAlpha = color.a; + } + for (var j = 0; j < triangles.length; j += 3) { + var t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + var x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + var x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + var 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + }; + SkeletonRenderer.prototype.drawTriangle = function (img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + var ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + }; + SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = region.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var vertices = this.vertices; + var uvs = region.uvs; + vertices[spine.RegionAttachment.C1R] = color.r; + vertices[spine.RegionAttachment.C1G] = color.g; + vertices[spine.RegionAttachment.C1B] = color.b; + vertices[spine.RegionAttachment.C1A] = color.a; + vertices[spine.RegionAttachment.U1] = uvs[0]; + vertices[spine.RegionAttachment.V1] = uvs[1]; + vertices[spine.RegionAttachment.C2R] = color.r; + vertices[spine.RegionAttachment.C2G] = color.g; + vertices[spine.RegionAttachment.C2B] = color.b; + vertices[spine.RegionAttachment.C2A] = color.a; + vertices[spine.RegionAttachment.U2] = uvs[2]; + vertices[spine.RegionAttachment.V2] = uvs[3]; + vertices[spine.RegionAttachment.C3R] = color.r; + vertices[spine.RegionAttachment.C3G] = color.g; + vertices[spine.RegionAttachment.C3B] = color.b; + vertices[spine.RegionAttachment.C3A] = color.a; + vertices[spine.RegionAttachment.U3] = uvs[4]; + vertices[spine.RegionAttachment.V3] = uvs[5]; + vertices[spine.RegionAttachment.C4R] = color.r; + vertices[spine.RegionAttachment.C4G] = color.g; + vertices[spine.RegionAttachment.C4B] = color.b; + vertices[spine.RegionAttachment.C4A] = color.a; + vertices[spine.RegionAttachment.U4] = uvs[6]; + vertices[spine.RegionAttachment.V4] = uvs[7]; + return vertices; + }; + SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = mesh.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + var numVertices = mesh.worldVerticesLength / 2; + if (this.vertices.length < mesh.worldVerticesLength) { + this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength); + } + var vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var uvs = mesh.uvs; + for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4; + return SkeletonRenderer; + }()); + canvas.SkeletonRenderer = SkeletonRenderer; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +//# sourceMappingURL=spine-canvas.js.map \ No newline at end of file diff --git a/release/MAC版本/lib/3.7/spine-canvas.js b/release/MAC版本/lib/3.7/spine-canvas.js new file mode 100644 index 0000000..7288639 --- /dev/null +++ b/release/MAC版本/lib/3.7/spine-canvas.js @@ -0,0 +1,7117 @@ +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var spine; +(function (spine) { + var Animation = (function () { + function Animation(name, timelines, duration) { + if (name == null) + throw new Error("name cannot be null."); + if (timelines == null) + throw new Error("timelines cannot be null."); + this.name = name; + this.timelines = timelines; + this.duration = duration; + } + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + }; + Animation.binarySearch = function (values, target, step) { + if (step === void 0) { step = 1; } + var low = 0; + var high = values.length / step - 2; + if (high == 0) + return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) + return (low + 1) * step; + current = (low + high) >>> 1; + } + }; + Animation.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) + return i; + return -1; + }; + return Animation; + }()); + spine.Animation = Animation; + var MixBlend; + (function (MixBlend) { + MixBlend[MixBlend["setup"] = 0] = "setup"; + MixBlend[MixBlend["first"] = 1] = "first"; + MixBlend[MixBlend["replace"] = 2] = "replace"; + MixBlend[MixBlend["add"] = 3] = "add"; + })(MixBlend = spine.MixBlend || (spine.MixBlend = {})); + var MixDirection; + (function (MixDirection) { + MixDirection[MixDirection["in"] = 0] = "in"; + MixDirection[MixDirection["out"] = 1] = "out"; + })(MixDirection = spine.MixDirection || (spine.MixDirection = {})); + var TimelineType; + (function (TimelineType) { + TimelineType[TimelineType["rotate"] = 0] = "rotate"; + TimelineType[TimelineType["translate"] = 1] = "translate"; + TimelineType[TimelineType["scale"] = 2] = "scale"; + TimelineType[TimelineType["shear"] = 3] = "shear"; + TimelineType[TimelineType["attachment"] = 4] = "attachment"; + TimelineType[TimelineType["color"] = 5] = "color"; + TimelineType[TimelineType["deform"] = 6] = "deform"; + TimelineType[TimelineType["event"] = 7] = "event"; + TimelineType[TimelineType["drawOrder"] = 8] = "drawOrder"; + TimelineType[TimelineType["ikConstraint"] = 9] = "ikConstraint"; + TimelineType[TimelineType["transformConstraint"] = 10] = "transformConstraint"; + TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; + TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; + TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; + TimelineType[TimelineType["twoColor"] = 14] = "twoColor"; + })(TimelineType = spine.TimelineType || (spine.TimelineType = {})); + var CurveTimeline = (function () { + function CurveTimeline(frameCount) { + if (frameCount <= 0) + throw new Error("frameCount must be > 0: " + frameCount); + this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE); + } + CurveTimeline.prototype.getFrameCount = function () { + return this.curves.length / CurveTimeline.BEZIER_SIZE + 1; + }; + CurveTimeline.prototype.setLinear = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR; + }; + CurveTimeline.prototype.setStepped = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED; + }; + CurveTimeline.prototype.getCurveType = function (frameIndex) { + var index = frameIndex * CurveTimeline.BEZIER_SIZE; + if (index == this.curves.length) + return CurveTimeline.LINEAR; + var type = this.curves[index]; + if (type == CurveTimeline.LINEAR) + return CurveTimeline.LINEAR; + if (type == CurveTimeline.STEPPED) + return CurveTimeline.STEPPED; + return CurveTimeline.BEZIER; + }; + CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) { + var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03; + var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; + var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var curves = this.curves; + curves[i++] = CurveTimeline.BEZIER; + var x = dfx, y = dfy; + for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + }; + CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) { + percent = spine.MathUtils.clamp(percent, 0, 1); + var curves = this.curves; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var type = curves[i]; + if (type == CurveTimeline.LINEAR) + return percent; + if (type == CurveTimeline.STEPPED) + return 0; + i++; + var x = 0; + for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + x = curves[i]; + if (x >= percent) { + var prevX = void 0, prevY = void 0; + if (i == start) { + prevX = 0; + prevY = 0; + } + else { + prevX = curves[i - 2]; + prevY = curves[i - 1]; + } + return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + var y = curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); + }; + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; + return CurveTimeline; + }()); + spine.CurveTimeline = CurveTimeline; + var RotateTimeline = (function (_super) { + __extends(RotateTimeline, _super); + function RotateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount << 1); + return _this; + } + RotateTimeline.prototype.getPropertyId = function () { + return (TimelineType.rotate << 24) + this.boneIndex; + }; + RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) { + frameIndex <<= 1; + this.frames[frameIndex] = time; + this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; + }; + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation; + return; + case MixBlend.first: + var r_1 = bone.data.rotation - bone.rotation; + bone.rotation += (r_1 - (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360) * alpha; + } + return; + } + if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { + var r_2 = frames[frames.length + RotateTimeline.PREV_ROTATION]; + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation + r_2 * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + r_2 += bone.data.rotation - bone.rotation; + r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360; + case MixBlend.add: + bone.rotation += r_2 * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES); + var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); + var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; + r = prevRotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * percent; + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + r += bone.data.rotation - bone.rotation; + case MixBlend.add: + bone.rotation += (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha; + } + }; + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; + return RotateTimeline; + }(CurveTimeline)); + spine.RotateTimeline = RotateTimeline; + var TranslateTimeline = (function (_super) { + __extends(TranslateTimeline, _super); + function TranslateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + return _this; + } + TranslateTimeline.prototype.getPropertyId = function () { + return (TimelineType.translate << 24) + this.boneIndex; + }; + TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) { + frameIndex *= TranslateTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TranslateTimeline.X] = x; + this.frames[frameIndex + TranslateTimeline.Y] = y; + }; + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixBlend.first: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) { + x = frames[frames.length + TranslateTimeline.PREV_X]; + y = frames[frames.length + TranslateTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES); + x = frames[frame + TranslateTimeline.PREV_X]; + y = frames[frame + TranslateTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime)); + x += (frames[frame + TranslateTimeline.X] - x) * percent; + y += (frames[frame + TranslateTimeline.Y] - y) * percent; + } + switch (blend) { + case MixBlend.setup: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case MixBlend.add: + bone.x += x * alpha; + bone.y += y * alpha; + } + }; + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; + return TranslateTimeline; + }(CurveTimeline)); + spine.TranslateTimeline = TranslateTimeline; + var ScaleTimeline = (function (_super) { + __extends(ScaleTimeline, _super); + function ScaleTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ScaleTimeline.prototype.getPropertyId = function () { + return (TimelineType.scale << 24) + this.boneIndex; + }; + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixBlend.first: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) { + x = frames[frames.length + ScaleTimeline.PREV_X] * bone.data.scaleX; + y = frames[frames.length + ScaleTimeline.PREV_Y] * bone.data.scaleY; + } + else { + var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES); + x = frames[frame + ScaleTimeline.PREV_X]; + y = frames[frame + ScaleTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime)); + x = (x + (frames[frame + ScaleTimeline.X] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY; + } + if (alpha == 1) { + if (blend == MixBlend.add) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } + else { + bone.scaleX = x; + bone.scaleY = y; + } + } + else { + var bx = 0, by = 0; + if (direction == MixDirection.out) { + switch (blend) { + case MixBlend.setup: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - by) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - by) * alpha; + break; + case MixBlend.add: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bone.data.scaleX) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - bone.data.scaleY) * alpha; + } + } + else { + switch (blend) { + case MixBlend.setup: + bx = Math.abs(bone.data.scaleX) * spine.MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * spine.MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bx = Math.abs(bone.scaleX) * spine.MathUtils.signum(x); + by = Math.abs(bone.scaleY) * spine.MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case MixBlend.add: + bx = spine.MathUtils.signum(x); + by = spine.MathUtils.signum(y); + bone.scaleX = Math.abs(bone.scaleX) * bx + (x - Math.abs(bone.data.scaleX) * bx) * alpha; + bone.scaleY = Math.abs(bone.scaleY) * by + (y - Math.abs(bone.data.scaleY) * by) * alpha; + } + } + } + }; + return ScaleTimeline; + }(TranslateTimeline)); + spine.ScaleTimeline = ScaleTimeline; + var ShearTimeline = (function (_super) { + __extends(ShearTimeline, _super); + function ShearTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ShearTimeline.prototype.getPropertyId = function () { + return (TimelineType.shear << 24) + this.boneIndex; + }; + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixBlend.first: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ShearTimeline.ENTRIES]) { + x = frames[frames.length + ShearTimeline.PREV_X]; + y = frames[frames.length + ShearTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES); + x = frames[frame + ShearTimeline.PREV_X]; + y = frames[frame + ShearTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime)); + x = x + (frames[frame + ShearTimeline.X] - x) * percent; + y = y + (frames[frame + ShearTimeline.Y] - y) * percent; + } + switch (blend) { + case MixBlend.setup: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case MixBlend.add: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + }; + return ShearTimeline; + }(TranslateTimeline)); + spine.ShearTimeline = ShearTimeline; + var ColorTimeline = (function (_super) { + __extends(ColorTimeline, _super); + function ColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + return _this; + } + ColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.color << 24) + this.slotIndex; + }; + ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) { + frameIndex *= ColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + ColorTimeline.R] = r; + this.frames[frameIndex + ColorTimeline.G] = g; + this.frames[frameIndex + ColorTimeline.B] = b; + this.frames[frameIndex + ColorTimeline.A] = a; + }; + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + slot.color.setFromColor(slot.data.color); + return; + case MixBlend.first: + var color = slot.color, setup = slot.data.color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } + return; + } + var r = 0, g = 0, b = 0, a = 0; + if (time >= frames[frames.length - ColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + ColorTimeline.PREV_R]; + g = frames[i + ColorTimeline.PREV_G]; + b = frames[i + ColorTimeline.PREV_B]; + a = frames[i + ColorTimeline.PREV_A]; + } + else { + var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES); + r = frames[frame + ColorTimeline.PREV_R]; + g = frames[frame + ColorTimeline.PREV_G]; + b = frames[frame + ColorTimeline.PREV_B]; + a = frames[frame + ColorTimeline.PREV_A]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + ColorTimeline.R] - r) * percent; + g += (frames[frame + ColorTimeline.G] - g) * percent; + b += (frames[frame + ColorTimeline.B] - b) * percent; + a += (frames[frame + ColorTimeline.A] - a) * percent; + } + if (alpha == 1) + slot.color.set(r, g, b, a); + else { + var color = slot.color; + if (blend == MixBlend.setup) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + }; + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; + return ColorTimeline; + }(CurveTimeline)); + spine.ColorTimeline = ColorTimeline; + var TwoColorTimeline = (function (_super) { + __extends(TwoColorTimeline, _super); + function TwoColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES); + return _this; + } + TwoColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.twoColor << 24) + this.slotIndex; + }; + TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + }; + TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + return; + case MixBlend.first: + var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0); + } + return; + } + var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + TwoColorTimeline.PREV_R]; + g = frames[i + TwoColorTimeline.PREV_G]; + b = frames[i + TwoColorTimeline.PREV_B]; + a = frames[i + TwoColorTimeline.PREV_A]; + r2 = frames[i + TwoColorTimeline.PREV_R2]; + g2 = frames[i + TwoColorTimeline.PREV_G2]; + b2 = frames[i + TwoColorTimeline.PREV_B2]; + } + else { + var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES); + r = frames[frame + TwoColorTimeline.PREV_R]; + g = frames[frame + TwoColorTimeline.PREV_G]; + b = frames[frame + TwoColorTimeline.PREV_B]; + a = frames[frame + TwoColorTimeline.PREV_A]; + r2 = frames[frame + TwoColorTimeline.PREV_R2]; + g2 = frames[frame + TwoColorTimeline.PREV_G2]; + b2 = frames[frame + TwoColorTimeline.PREV_B2]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + TwoColorTimeline.R] - r) * percent; + g += (frames[frame + TwoColorTimeline.G] - g) * percent; + b += (frames[frame + TwoColorTimeline.B] - b) * percent; + a += (frames[frame + TwoColorTimeline.A] - a) * percent; + r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent; + g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent; + b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent; + } + if (alpha == 1) { + slot.color.set(r, g, b, a); + slot.darkColor.set(r2, g2, b2, 1); + } + else { + var light = slot.color, dark = slot.darkColor; + if (blend == MixBlend.setup) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + }; + TwoColorTimeline.ENTRIES = 8; + TwoColorTimeline.PREV_TIME = -8; + TwoColorTimeline.PREV_R = -7; + TwoColorTimeline.PREV_G = -6; + TwoColorTimeline.PREV_B = -5; + TwoColorTimeline.PREV_A = -4; + TwoColorTimeline.PREV_R2 = -3; + TwoColorTimeline.PREV_G2 = -2; + TwoColorTimeline.PREV_B2 = -1; + TwoColorTimeline.R = 1; + TwoColorTimeline.G = 2; + TwoColorTimeline.B = 3; + TwoColorTimeline.A = 4; + TwoColorTimeline.R2 = 5; + TwoColorTimeline.G2 = 6; + TwoColorTimeline.B2 = 7; + return TwoColorTimeline; + }(CurveTimeline)); + spine.TwoColorTimeline = TwoColorTimeline; + var AttachmentTimeline = (function () { + function AttachmentTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.attachmentNames = new Array(frameCount); + } + AttachmentTimeline.prototype.getPropertyId = function () { + return (TimelineType.attachment << 24) + this.slotIndex; + }; + AttachmentTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }; + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (direction == MixDirection.out && blend == MixBlend.setup) { + var attachmentName_1 = slot.data.attachmentName; + slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1)); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (blend == MixBlend.setup || blend == MixBlend.first) { + var attachmentName_2 = slot.data.attachmentName; + slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2)); + } + return; + } + var frameIndex = 0; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = Animation.binarySearch(frames, time, 1) - 1; + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex] + .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + return AttachmentTimeline; + }()); + spine.AttachmentTimeline = AttachmentTimeline; + var zeros = null; + var DeformTimeline = (function (_super) { + __extends(DeformTimeline, _super); + function DeformTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount); + _this.frameVertices = new Array(frameCount); + if (zeros == null) + zeros = spine.Utils.newFloatArray(64); + return _this; + } + DeformTimeline.prototype.getPropertyId = function () { + return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex; + }; + DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { + this.frames[frameIndex] = time; + this.frameVertices[frameIndex] = vertices; + }; + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + var slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) + return; + var verticesArray = slot.attachmentVertices; + if (verticesArray.length == 0) + blend = MixBlend.setup; + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + var frames = this.frames; + if (time < frames[0]) { + var vertexAttachment = slotAttachment; + switch (blend) { + case MixBlend.setup: + verticesArray.length = 0; + return; + case MixBlend.first: + if (alpha == 1) { + verticesArray.length = 0; + break; + } + var vertices_1 = spine.Utils.setArraySize(verticesArray, vertexCount); + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] += (setupVertices[i] - vertices_1[i]) * alpha; + } + else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] *= alpha; + } + } + return; + } + var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); + if (time >= frames[frames.length - 1]) { + var lastVertices = frameVertices[frames.length - 1]; + if (alpha == 1) { + if (blend == MixBlend.add) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_1 = 0; i_1 < vertexCount; i_1++) { + vertices[i_1] += lastVertices[i_1] - setupVertices[i_1]; + } + } + else { + for (var i_2 = 0; i_2 < vertexCount; i_2++) + vertices[i_2] += lastVertices[i_2]; + } + } + else { + spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); + } + } + else { + switch (blend) { + case MixBlend.setup: { + var vertexAttachment_1 = slotAttachment; + if (vertexAttachment_1.bones == null) { + var setupVertices = vertexAttachment_1.vertices; + for (var i_3 = 0; i_3 < vertexCount; i_3++) { + var setup = setupVertices[i_3]; + vertices[i_3] = setup + (lastVertices[i_3] - setup) * alpha; + } + } + else { + for (var i_4 = 0; i_4 < vertexCount; i_4++) + vertices[i_4] = lastVertices[i_4] * alpha; + } + break; + } + case MixBlend.first: + case MixBlend.replace: + for (var i_5 = 0; i_5 < vertexCount; i_5++) + vertices[i_5] += (lastVertices[i_5] - vertices[i_5]) * alpha; + case MixBlend.add: + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_6 = 0; i_6 < vertexCount; i_6++) { + vertices[i_6] += (lastVertices[i_6] - setupVertices[i_6]) * alpha; + } + } + else { + for (var i_7 = 0; i_7 < vertexCount; i_7++) + vertices[i_7] += lastVertices[i_7] * alpha; + } + } + } + return; + } + var frame = Animation.binarySearch(frames, time); + var prevVertices = frameVertices[frame - 1]; + var nextVertices = frameVertices[frame]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + if (alpha == 1) { + if (blend == MixBlend.add) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_8 = 0; i_8 < vertexCount; i_8++) { + var prev = prevVertices[i_8]; + vertices[i_8] += prev + (nextVertices[i_8] - prev) * percent - setupVertices[i_8]; + } + } + else { + for (var i_9 = 0; i_9 < vertexCount; i_9++) { + var prev = prevVertices[i_9]; + vertices[i_9] += prev + (nextVertices[i_9] - prev) * percent; + } + } + } + else { + for (var i_10 = 0; i_10 < vertexCount; i_10++) { + var prev = prevVertices[i_10]; + vertices[i_10] = prev + (nextVertices[i_10] - prev) * percent; + } + } + } + else { + switch (blend) { + case MixBlend.setup: { + var vertexAttachment_2 = slotAttachment; + if (vertexAttachment_2.bones == null) { + var setupVertices = vertexAttachment_2.vertices; + for (var i_11 = 0; i_11 < vertexCount; i_11++) { + var prev = prevVertices[i_11], setup = setupVertices[i_11]; + vertices[i_11] = setup + (prev + (nextVertices[i_11] - prev) * percent - setup) * alpha; + } + } + else { + for (var i_12 = 0; i_12 < vertexCount; i_12++) { + var prev = prevVertices[i_12]; + vertices[i_12] = (prev + (nextVertices[i_12] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend.first: + case MixBlend.replace: + for (var i_13 = 0; i_13 < vertexCount; i_13++) { + var prev = prevVertices[i_13]; + vertices[i_13] += (prev + (nextVertices[i_13] - prev) * percent - vertices[i_13]) * alpha; + } + break; + case MixBlend.add: + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_14 = 0; i_14 < vertexCount; i_14++) { + var prev = prevVertices[i_14]; + vertices[i_14] += (prev + (nextVertices[i_14] - prev) * percent - setupVertices[i_14]) * alpha; + } + } + else { + for (var i_15 = 0; i_15 < vertexCount; i_15++) { + var prev = prevVertices[i_15]; + vertices[i_15] += (prev + (nextVertices[i_15] - prev) * percent) * alpha; + } + } + } + } + }; + return DeformTimeline; + }(CurveTimeline)); + spine.DeformTimeline = DeformTimeline; + var EventTimeline = (function () { + function EventTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.events = new Array(frameCount); + } + EventTimeline.prototype.getPropertyId = function () { + return TimelineType.event << 24; + }; + EventTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + EventTimeline.prototype.setFrame = function (frameIndex, event) { + this.frames[frameIndex] = event.time; + this.events[frameIndex] = event; + }; + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (firedEvents == null) + return; + var frames = this.frames; + var frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } + else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + var frame = 0; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.binarySearch(frames, lastTime); + var frameTime = frames[frame]; + while (frame > 0) { + if (frames[frame - 1] != frameTime) + break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.push(this.events[frame]); + }; + return EventTimeline; + }()); + spine.EventTimeline = EventTimeline; + var DrawOrderTimeline = (function () { + function DrawOrderTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.drawOrders = new Array(frameCount); + } + DrawOrderTimeline.prototype.getPropertyId = function () { + return TimelineType.drawOrder << 24; + }; + DrawOrderTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) { + this.frames[frameIndex] = time; + this.drawOrders[frameIndex] = drawOrder; + }; + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var drawOrder = skeleton.drawOrder; + var slots = skeleton.slots; + if (direction == MixDirection.out && blend == MixBlend.setup) { + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (blend == MixBlend.setup || blend == MixBlend.first) + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frame = 0; + if (time >= frames[frames.length - 1]) + frame = frames.length - 1; + else + frame = Animation.binarySearch(frames, time) - 1; + var drawOrderToSetupIndex = this.drawOrders[frame]; + if (drawOrderToSetupIndex == null) + spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length); + else { + for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + }; + return DrawOrderTimeline; + }()); + spine.DrawOrderTimeline = DrawOrderTimeline; + var IkConstraintTimeline = (function (_super) { + __extends(IkConstraintTimeline, _super); + function IkConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + return _this; + } + IkConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; + }; + IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection, compress, stretch) { + frameIndex *= IkConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; + this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; + this.frames[frameIndex + IkConstraintTimeline.COMPRESS] = compress ? 1 : 0; + this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0; + }; + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case MixBlend.first: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { + if (blend == MixBlend.setup) { + constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; + if (direction == MixDirection.out) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + else { + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frames.length + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frames.length + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + else { + constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; + if (direction == MixDirection["in"]) { + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frames.length + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frames.length + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + return; + } + var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES); + var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); + if (blend == MixBlend.setup) { + constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; + if (direction == MixDirection.out) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + else { + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frame + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frame + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + else { + constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; + if (direction == MixDirection["in"]) { + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frame + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frame + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + }; + IkConstraintTimeline.ENTRIES = 5; + IkConstraintTimeline.PREV_TIME = -5; + IkConstraintTimeline.PREV_MIX = -4; + IkConstraintTimeline.PREV_BEND_DIRECTION = -3; + IkConstraintTimeline.PREV_COMPRESS = -2; + IkConstraintTimeline.PREV_STRETCH = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.BEND_DIRECTION = 2; + IkConstraintTimeline.COMPRESS = 3; + IkConstraintTimeline.STRETCH = 4; + return IkConstraintTimeline; + }(CurveTimeline)); + spine.IkConstraintTimeline = IkConstraintTimeline; + var TransformConstraintTimeline = (function (_super) { + __extends(TransformConstraintTimeline, _super); + function TransformConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + return _this; + } + TransformConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; + }; + TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) { + frameIndex *= TransformConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix; + this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; + this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; + }; + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (time < frames[0]) { + var data = constraint.data; + switch (blend) { + case MixBlend.setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixBlend.first: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; + } + return; + } + var rotate = 0, translate = 0, scale = 0, shear = 0; + if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) { + var i = frames.length; + rotate = frames[i + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[i + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[i + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[i + TransformConstraintTimeline.PREV_SHEAR]; + } + else { + var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES); + rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[frame + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent; + scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; + shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; + } + if (blend == MixBlend.setup) { + var data = constraint.data; + constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; + constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; + constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; + constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + constraint.scaleMix += (scale - constraint.scaleMix) * alpha; + constraint.shearMix += (shear - constraint.shearMix) * alpha; + } + }; + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; + return TransformConstraintTimeline; + }(CurveTimeline)); + spine.TransformConstraintTimeline = TransformConstraintTimeline; + var PathConstraintPositionTimeline = (function (_super) { + __extends(PathConstraintPositionTimeline, _super); + function PathConstraintPositionTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + return _this; + } + PathConstraintPositionTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; + }; + PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) { + frameIndex *= PathConstraintPositionTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; + }; + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.position = constraint.data.position; + return; + case MixBlend.first: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } + return; + } + var position = 0; + if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES]) + position = frames[frames.length + PathConstraintPositionTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES); + position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); + position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; + } + if (blend == MixBlend.setup) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + }; + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; + return PathConstraintPositionTimeline; + }(CurveTimeline)); + spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; + var PathConstraintSpacingTimeline = (function (_super) { + __extends(PathConstraintSpacingTimeline, _super); + function PathConstraintSpacingTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + PathConstraintSpacingTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; + }; + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.spacing = constraint.data.spacing; + return; + case MixBlend.first: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } + return; + } + var spacing = 0; + if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES]) + spacing = frames[frames.length + PathConstraintSpacingTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES); + spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); + spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; + } + if (blend == MixBlend.setup) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + }; + return PathConstraintSpacingTimeline; + }(PathConstraintPositionTimeline)); + spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline; + var PathConstraintMixTimeline = (function (_super) { + __extends(PathConstraintMixTimeline, _super); + function PathConstraintMixTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + return _this; + } + PathConstraintMixTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; + }; + PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) { + frameIndex *= PathConstraintMixTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; + }; + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixBlend.first: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; + } + return; + } + var rotate = 0, translate = 0; + if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) { + rotate = frames[frames.length + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frames.length + PathConstraintMixTimeline.PREV_TRANSLATE]; + } + else { + var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES); + rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; + } + if (blend == MixBlend.setup) { + constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; + constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + } + }; + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; + return PathConstraintMixTimeline; + }(CurveTimeline)); + spine.PathConstraintMixTimeline = PathConstraintMixTimeline; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationState = (function () { + function AnimationState(data) { + this.tracks = new Array(); + this.events = new Array(); + this.listeners = new Array(); + this.queue = new EventQueue(this); + this.propertyIDs = new spine.IntSet(); + this.animationsChanged = false; + this.timeScale = 1; + this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); + this.data = data; + } + AnimationState.prototype.update = function (delta) { + delta *= this.timeScale; + var tracks = this.tracks; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + var currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + var next = current.next; + if (next != null) { + var nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime = current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom != null) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } + else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) { + var from = current.mixingFrom; + current.mixingFrom = null; + if (from != null) + from.mixingTo = null; + while (from != null) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + }; + AnimationState.prototype.updateMixingFrom = function (to, delta) { + var from = to.mixingFrom; + if (from == null) + return true; + var finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + }; + AnimationState.prototype.apply = function (skeleton) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + var events = this.events; + var tracks = this.tracks; + var applied = false; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null || current.delay > 0) + continue; + applied = true; + var blend = i == 0 ? spine.MixBlend.first : current.mixBlend; + var mix = current.alpha; + if (current.mixingFrom != null) + mix *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && current.next == null) + mix = 0; + var animationLast = current.animationLast, animationTime = current.getAnimationTime(); + var timelineCount = current.animation.timelines.length; + var timelines = current.animation.timelines; + if ((i == 0 && mix == 1) || blend == spine.MixBlend.add) { + for (var ii = 0; ii < timelineCount; ii++) + timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection["in"]); + } + else { + var timelineMode = current.timelineMode; + var firstFrame = current.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = current.timelinesRotation; + for (var ii = 0; ii < timelineCount; ii++) { + var timeline = timelines[ii]; + var timelineBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup; + if (timeline instanceof spine.RotateTimeline) { + this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame); + } + else { + spine.Utils.webkit602BugfixHelper(mix, blend); + timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection["in"]); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + this.queue.drain(); + return applied; + }; + AnimationState.prototype.applyMixingFrom = function (to, skeleton, blend) { + var from = to.mixingFrom; + if (from.mixingFrom != null) + this.applyMixingFrom(from, skeleton, blend); + var mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == spine.MixBlend.first) + blend = spine.MixBlend.setup; + } + else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != spine.MixBlend.first) + blend = from.mixBlend; + } + var events = mix < from.eventThreshold ? this.events : null; + var attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + var animationLast = from.animationLast, animationTime = from.getAnimationTime(); + var timelineCount = from.animation.timelines.length; + var timelines = from.animation.timelines; + var alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + if (blend == spine.MixBlend.add) { + for (var i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, spine.MixDirection.out); + } + else { + var timelineMode = from.timelineMode; + var timelineHoldMix = from.timelineHoldMix; + var firstFrame = from.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = from.timelinesRotation; + from.totalAlpha = 0; + for (var i = 0; i < timelineCount; i++) { + var timeline = timelines[i]; + var direction = spine.MixDirection.out; + var timelineBlend = void 0; + var alpha = 0; + switch (timelineMode[i]) { + case AnimationState.SUBSEQUENT: + if (!attachments && timeline instanceof spine.AttachmentTimeline) + continue; + if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case AnimationState.FIRST: + timelineBlend = spine.MixBlend.setup; + alpha = alphaMix; + break; + case AnimationState.HOLD: + timelineBlend = spine.MixBlend.setup; + alpha = alphaHold; + break; + default: + timelineBlend = spine.MixBlend.setup; + var holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame); + else { + spine.Utils.webkit602BugfixHelper(alpha, blend); + if (timelineBlend == spine.MixBlend.setup) { + if (timeline instanceof spine.AttachmentTimeline) { + if (attachments) + direction = spine.MixDirection.out; + } + else if (timeline instanceof spine.DrawOrderTimeline) { + if (drawOrder) + direction = spine.MixDirection.out; + } + } + timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + }; + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, spine.MixDirection["in"]); + return; + } + var rotateTimeline = timeline; + var frames = rotateTimeline.frames; + var bone = skeleton.bones[rotateTimeline.boneIndex]; + var r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case spine.MixBlend.setup: + bone.rotation = bone.data.rotation; + default: + return; + case spine.MixBlend.first: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } + else { + r1 = blend == spine.MixBlend.setup ? bone.data.rotation : bone.rotation; + if (time >= frames[frames.length - spine.RotateTimeline.ENTRIES]) + r2 = bone.data.rotation + frames[frames.length + spine.RotateTimeline.PREV_ROTATION]; + else { + var frame = spine.Animation.binarySearch(frames, time, spine.RotateTimeline.ENTRIES); + var prevRotation = frames[frame + spine.RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + spine.RotateTimeline.PREV_TIME] - frameTime)); + r2 = frames[frame + spine.RotateTimeline.ROTATION] - prevRotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + r2 = prevRotation + r2 * percent + bone.data.rotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + } + } + var total = 0, diff = r2 - r1; + diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } + else { + var lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } + else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + var current = diff > 0, dir = lastTotal >= 0; + if (spine.MathUtils.signum(lastDiff) != spine.MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * spine.MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * spine.MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360; + }; + AnimationState.prototype.queueEvents = function (entry, animationTime) { + var animationStart = entry.animationStart, animationEnd = entry.animationEnd; + var duration = animationEnd - animationStart; + var trackLastWrapped = entry.trackLast % duration; + var events = this.events; + var i = 0, n = events.length; + for (; i < n; i++) { + var event_1 = events[i]; + if (event_1.time < trackLastWrapped) + break; + if (event_1.time > animationEnd) + continue; + this.queue.event(entry, event_1); + } + var complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + var event_2 = events[i]; + if (event_2.time < animationStart) + continue; + this.queue.event(entry, events[i]); + } + }; + AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.clearTrack = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return; + var current = this.tracks[trackIndex]; + if (current == null) + return; + this.queue.end(current); + this.disposeNext(current); + var entry = current; + while (true) { + var from = entry.mixingFrom; + if (from == null) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + }; + AnimationState.prototype.setCurrent = function (index, current, interrupt) { + var from = this.expandToIndex(index); + this.tracks[index] = current; + if (from != null) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom != null && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + }; + AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + }; + AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) { + if (animation == null) + throw new Error("animation cannot be null."); + var interrupt = true; + var current = this.expandToIndex(trackIndex); + if (current != null) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.disposeNext(current); + current = current.mixingFrom; + interrupt = false; + } + else + this.disposeNext(current); + } + var entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + }; + AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + }; + AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) { + if (animation == null) + throw new Error("animation cannot be null."); + var last = this.expandToIndex(trackIndex); + if (last != null) { + while (last.next != null) + last = last.next; + } + var entry = this.trackEntry(trackIndex, animation, loop, last); + if (last == null) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } + else { + last.next = entry; + if (delay <= 0) { + var duration = last.animationEnd - last.animationStart; + if (duration != 0) { + if (last.loop) + delay += duration * (1 + ((last.trackTime / duration) | 0)); + else + delay += Math.max(duration, last.trackTime); + delay -= this.data.getMix(last.animation, animation); + } + else + delay = last.trackTime; + } + } + entry.delay = delay; + return entry; + }; + AnimationState.prototype.setEmptyAnimation = function (trackIndex, mixDuration) { + var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.addEmptyAnimation = function (trackIndex, mixDuration, delay) { + if (delay <= 0) + delay -= mixDuration; + var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) { + var current = this.tracks[i]; + if (current != null) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.expandToIndex = function (index) { + if (index < this.tracks.length) + return this.tracks[index]; + spine.Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + }; + AnimationState.prototype.trackEntry = function (trackIndex, animation, loop, last) { + var entry = this.trackEntryPool.obtain(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.interruptAlpha = 1; + entry.mixTime = 0; + entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); + return entry; + }; + AnimationState.prototype.disposeNext = function (entry) { + var next = entry.next; + while (next != null) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + }; + AnimationState.prototype._animationsChanged = function () { + this.animationsChanged = false; + this.propertyIDs.clear(); + for (var i = 0, n = this.tracks.length; i < n; i++) { + var entry = this.tracks[i]; + if (entry == null) + continue; + while (entry.mixingFrom != null) + entry = entry.mixingFrom; + do { + if (entry.mixingFrom == null || entry.mixBlend != spine.MixBlend.add) + this.setTimelineModes(entry); + entry = entry.mixingTo; + } while (entry != null); + } + }; + AnimationState.prototype.setTimelineModes = function (entry) { + var to = entry.mixingTo; + var timelines = entry.animation.timelines; + var timelinesCount = entry.animation.timelines.length; + var timelineMode = spine.Utils.setArraySize(entry.timelineMode, timelinesCount); + entry.timelineHoldMix.length = 0; + var timelineDipMix = spine.Utils.setArraySize(entry.timelineHoldMix, timelinesCount); + var propertyIDs = this.propertyIDs; + if (to != null && to.holdPrevious) { + for (var i = 0; i < timelinesCount; i++) { + propertyIDs.add(timelines[i].getPropertyId()); + timelineMode[i] = AnimationState.HOLD; + } + return; + } + outer: for (var i = 0; i < timelinesCount; i++) { + var id = timelines[i].getPropertyId(); + if (!propertyIDs.add(id)) + timelineMode[i] = AnimationState.SUBSEQUENT; + else if (to == null || !this.hasTimeline(to, id)) + timelineMode[i] = AnimationState.FIRST; + else { + for (var next = to.mixingTo; next != null; next = next.mixingTo) { + if (this.hasTimeline(next, id)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = AnimationState.HOLD_MIX; + timelineDipMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = AnimationState.HOLD; + } + } + }; + AnimationState.prototype.hasTimeline = function (entry, id) { + var timelines = entry.animation.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + if (timelines[i].getPropertyId() == id) + return true; + return false; + }; + AnimationState.prototype.getCurrent = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + }; + AnimationState.prototype.addListener = function (listener) { + if (listener == null) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + }; + AnimationState.prototype.removeListener = function (listener) { + var index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + }; + AnimationState.prototype.clearListeners = function () { + this.listeners.length = 0; + }; + AnimationState.prototype.clearListenerNotifications = function () { + this.queue.clear(); + }; + AnimationState.emptyAnimation = new spine.Animation("", [], 0); + AnimationState.SUBSEQUENT = 0; + AnimationState.FIRST = 1; + AnimationState.HOLD = 2; + AnimationState.HOLD_MIX = 3; + return AnimationState; + }()); + spine.AnimationState = AnimationState; + var TrackEntry = (function () { + function TrackEntry() { + this.mixBlend = spine.MixBlend.replace; + this.timelineMode = new Array(); + this.timelineHoldMix = new Array(); + this.timelinesRotation = new Array(); + } + TrackEntry.prototype.reset = function () { + this.next = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + }; + TrackEntry.prototype.getAnimationTime = function () { + if (this.loop) { + var duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return (this.trackTime % duration) + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + }; + TrackEntry.prototype.setAnimationLast = function (animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + }; + TrackEntry.prototype.isComplete = function () { + return this.trackTime >= this.animationEnd - this.animationStart; + }; + TrackEntry.prototype.resetRotationDirections = function () { + this.timelinesRotation.length = 0; + }; + return TrackEntry; + }()); + spine.TrackEntry = TrackEntry; + var EventQueue = (function () { + function EventQueue(animState) { + this.objects = []; + this.drainDisabled = false; + this.animState = animState; + } + EventQueue.prototype.start = function (entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.interrupt = function (entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + }; + EventQueue.prototype.end = function (entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.dispose = function (entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + }; + EventQueue.prototype.complete = function (entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + }; + EventQueue.prototype.event = function (entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + }; + EventQueue.prototype.drain = function () { + if (this.drainDisabled) + return; + this.drainDisabled = true; + var objects = this.objects; + var listeners = this.animState.listeners; + for (var i = 0; i < objects.length; i += 2) { + var type = objects[i]; + var entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener != null && entry.listener.start) + entry.listener.start(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].start) + listeners[ii].start(entry); + break; + case EventType.interrupt: + if (entry.listener != null && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].interrupt) + listeners[ii].interrupt(entry); + break; + case EventType.end: + if (entry.listener != null && entry.listener.end) + entry.listener.end(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].end) + listeners[ii].end(entry); + case EventType.dispose: + if (entry.listener != null && entry.listener.dispose) + entry.listener.dispose(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].dispose) + listeners[ii].dispose(entry); + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener != null && entry.listener.complete) + entry.listener.complete(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].complete) + listeners[ii].complete(entry); + break; + case EventType.event: + var event_3 = objects[i++ + 2]; + if (entry.listener != null && entry.listener.event) + entry.listener.event(entry, event_3); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].event) + listeners[ii].event(entry, event_3); + break; + } + } + this.clear(); + this.drainDisabled = false; + }; + EventQueue.prototype.clear = function () { + this.objects.length = 0; + }; + return EventQueue; + }()); + spine.EventQueue = EventQueue; + var EventType; + (function (EventType) { + EventType[EventType["start"] = 0] = "start"; + EventType[EventType["interrupt"] = 1] = "interrupt"; + EventType[EventType["end"] = 2] = "end"; + EventType[EventType["dispose"] = 3] = "dispose"; + EventType[EventType["complete"] = 4] = "complete"; + EventType[EventType["event"] = 5] = "event"; + })(EventType = spine.EventType || (spine.EventType = {})); + var AnimationStateAdapter2 = (function () { + function AnimationStateAdapter2() { + } + AnimationStateAdapter2.prototype.start = function (entry) { + }; + AnimationStateAdapter2.prototype.interrupt = function (entry) { + }; + AnimationStateAdapter2.prototype.end = function (entry) { + }; + AnimationStateAdapter2.prototype.dispose = function (entry) { + }; + AnimationStateAdapter2.prototype.complete = function (entry) { + }; + AnimationStateAdapter2.prototype.event = function (entry, event) { + }; + return AnimationStateAdapter2; + }()); + spine.AnimationStateAdapter2 = AnimationStateAdapter2; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationStateData = (function () { + function AnimationStateData(skeletonData) { + this.animationToMixTime = {}; + this.defaultMix = 0; + if (skeletonData == null) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + AnimationStateData.prototype.setMix = function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (from == null) + throw new Error("Animation not found: " + fromName); + var to = this.skeletonData.findAnimation(toName); + if (to == null) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + }; + AnimationStateData.prototype.setMixWith = function (from, to, duration) { + if (from == null) + throw new Error("from cannot be null."); + if (to == null) + throw new Error("to cannot be null."); + var key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + }; + AnimationStateData.prototype.getMix = function (from, to) { + var key = from.name + "." + to.name; + var value = this.animationToMixTime[key]; + return value === undefined ? this.defaultMix : value; + }; + return AnimationStateData; + }()); + spine.AnimationStateData = AnimationStateData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AssetManager = (function () { + function AssetManager(textureLoader, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + } + AssetManager.downloadText = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.onload = function () { + if (request.status == 200) { + success(request.responseText); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.downloadBinary = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status == 200) { + success(new Uint8Array(request.response)); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.prototype.loadText = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + AssetManager.downloadText(path, function (data) { + _this.assets[path] = data; + if (success) + success(path, data); + _this.toLoad--; + _this.loaded++; + }, function (state, responseText) { + _this.errors[path] = "Couldn't load text " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load text " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.loadTexture = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + img.src = path; + }; + AssetManager.prototype.loadTextureData = function (path, data, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + img.src = data; + }; + AssetManager.prototype.loadTextureAtlas = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : ""; + path = this.pathPrefix + path; + this.toLoad++; + AssetManager.downloadText(path, function (atlasData) { + var pagesLoaded = { count: 0 }; + var atlasPages = new Array(); + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + atlasPages.push(parent + "/" + path); + var image = document.createElement("img"); + image.width = 16; + image.height = 16; + return new spine.FakeTexture(image); + }); + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + return; + } + var _loop_1 = function (atlasPage) { + var pageLoadError = false; + _this.loadTexture(atlasPage, function (imagePath, image) { + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + if (!pageLoadError) { + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + return _this.get(parent + "/" + path); + }); + _this.assets[path] = atlas; + if (success) + success(path, atlas); + _this.toLoad--; + _this.loaded++; + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + } + } + else { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + } + }, function (imagePath, errorMessage) { + pageLoadError = true; + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + }); + }; + for (var _i = 0, atlasPages_1 = atlasPages; _i < atlasPages_1.length; _i++) { + var atlasPage = atlasPages_1[_i]; + _loop_1(atlasPage); + } + }, function (state, responseText) { + _this.errors[path] = "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.get = function (path) { + path = this.pathPrefix + path; + return this.assets[path]; + }; + AssetManager.prototype.remove = function (path) { + path = this.pathPrefix + path; + var asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + this.assets[path] = null; + }; + AssetManager.prototype.removeAll = function () { + for (var key in this.assets) { + var asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + }; + AssetManager.prototype.isLoadingComplete = function () { + return this.toLoad == 0; + }; + AssetManager.prototype.getToLoad = function () { + return this.toLoad; + }; + AssetManager.prototype.getLoaded = function () { + return this.loaded; + }; + AssetManager.prototype.dispose = function () { + this.removeAll(); + }; + AssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + AssetManager.prototype.getErrors = function () { + return this.errors; + }; + return AssetManager; + }()); + spine.AssetManager = AssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AtlasAttachmentLoader = (function () { + function AtlasAttachmentLoader(atlas) { + this.atlas = atlas; + } + AtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.RegionAttachment(name); + attachment.setRegion(region); + return attachment; + }; + AtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.MeshAttachment(name); + attachment.region = region; + return attachment; + }; + AtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) { + return new spine.BoundingBoxAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { + return new spine.PathAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { + return new spine.PointAttachment(name); + }; + AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) { + return new spine.ClippingAttachment(name); + }; + return AtlasAttachmentLoader; + }()); + spine.AtlasAttachmentLoader = AtlasAttachmentLoader; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BlendMode; + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(BlendMode = spine.BlendMode || (spine.BlendMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var skeleton = this.skeleton; + var rotationY = rotation + 90 + shearY; + var sx = skeleton.scaleX; + var sy = skeleton.scaleY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX * sx; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY * sx; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX * sy; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case spine.TransformMode.Normal: { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case spine.TransformMode.OnlyTranslation: { + var rotationY = rotation + 90 + shearY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case spine.TransformMode.NoRotationOrReflection: { + var s = pa * pa + pc * pc; + var prx = 0; + if (s > 0.0001) { + s = Math.abs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; + } + else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; + } + var rx = rotation + shearX - prx; + var ry = rotation + shearY - prx + 90; + var la = spine.MathUtils.cosDeg(rx) * scaleX; + var lb = spine.MathUtils.cosDeg(ry) * scaleY; + var lc = spine.MathUtils.sinDeg(rx) * scaleX; + var ld = spine.MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: { + var cos = spine.MathUtils.cosDeg(rotation); + var sin = spine.MathUtils.sinDeg(rotation); + var za = (pa * cos + pb * sin) / this.skeleton.scaleX; + var zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + var s = Math.sqrt(za * za + zc * zc); + if (s > 0.00001) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.data.transformMode == spine.TransformMode.NoScale + && (pa * pd - pb * pc < 0) != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + var r = Math.PI / 2 + Math.atan2(zc, za); + var zb = Math.cos(r) * s; + var zd = Math.sin(r) * s; + var la = spine.MathUtils.cosDeg(shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; + var lc = spine.MathUtils.sinDeg(shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + }; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + }; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.c * this.c); + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.b * this.b + this.d * this.d); + }; + Bone.prototype.updateAppliedTransform = function () { + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + this.ax = this.worldX; + this.ay = this.worldY; + this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = (dx * pd * pid - dy * pb * pid); + this.ay = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + } + else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; + } + }; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; + }; + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + }; + Bone.prototype.worldToLocalRotation = function (worldRotation) { + var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg + this.rotation - this.shearX; + }; + Bone.prototype.localToWorldRotation = function (localRotation) { + localRotation -= this.rotation - this.shearX; + var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; + return Bone; + }()); + spine.Bone = Bone; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoneData = (function () { + function BoneData(index, name, parent) { + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + return BoneData; + }()); + spine.BoneData = BoneData; + var TransformMode; + (function (TransformMode) { + TransformMode[TransformMode["Normal"] = 0] = "Normal"; + TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; + TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(TransformMode = spine.TransformMode || (spine.TransformMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; +})(spine || (spine = {})); +var spine; +(function (spine) { + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.bendDirection = 0; + this.compress = false; + this.stretch = false; + this.mix = 1; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + IkConstraint.prototype.getOrder = function () { + return this.data.order; + }; + IkConstraint.prototype.apply = function () { + this.update(); + }; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.mix); + break; + } + }; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, compress, stretch, uniform, alpha) { + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var p = bone.parent; + var id = 1 / (p.a * p.d - p.b * p.c); + var x = targetX - p.worldX, y = targetY - p.worldY; + var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; + var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + var sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); + if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) { + var s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); + }; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, stretch, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + if (!parent.appliedValid) + parent.updateAppliedTransform(); + if (!child.appliedValid) + child.updateAppliedTransform(); + var px = parent.ax, py = parent.ay, psx = parent.ascaleX, sx = psx, psy = parent.ascaleY, csx = child.ascaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } + else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } + else + os2 = 0; + var cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + var u = Math.abs(psx - psy) <= 0.0001; + if (!u) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } + else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + var pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + var id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; + var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py, dd = tx * tx + ty * ty; + x = cwx - pp.worldX; + y = cwy - pp.worldY; + var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1 = 0, a2 = 0; + outer: if (u) { + l2 *= psx; + var cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + cos = -1; + else if (cos > 1) { + cos = 1; + if (stretch && l1 + l2 > 0.0001) + sx *= (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + } + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } + else { + a = psx * l2; + b = psy * l2; + var aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + var c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + var q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) / 2; + var r0 = q / c2, r1 = c / q; + var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + var os = Math.atan2(cy, cx) * s2; + var rotation = parent.arotation; + a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, parent.ascaleY, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * spine.MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + }; + return IkConstraint; + }()); + spine.IkConstraint = IkConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraintData = (function () { + function IkConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.bendDirection = 1; + this.compress = false; + this.stretch = false; + this.uniform = false; + this.mix = 1; + this.name = name; + } + return IkConstraintData; + }()); + spine.IkConstraintData = IkConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraint = (function () { + function PathConstraint(data, skeleton) { + this.position = 0; + this.spacing = 0; + this.rotateMix = 0; + this.translateMix = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + } + PathConstraint.prototype.apply = function () { + this.update(); + }; + PathConstraint.prototype.update = function () { + var attachment = this.target.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + return; + var rotateMix = this.rotateMix, translateMix = this.translateMix; + var translate = translateMix > 0, rotate = rotateMix > 0; + if (!translate && !rotate) + return; + var data = this.data; + var percentSpacing = data.spacingMode == spine.SpacingMode.Percent; + var rotateMode = data.rotateMode; + var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale; + var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + var bones = this.bones; + var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null; + var spacing = this.spacing; + if (scale || !percentSpacing) { + if (scale) + lengths = spine.Utils.setArraySize(this.lengths, boneCount); + var lengthSpacing = data.spacingMode == spine.SpacingMode.Length; + for (var i = 0, n = spacesCount - 1; i < n;) { + var bone = bones[i]; + var setupLength = bone.data.length; + if (setupLength < PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = 0; + } + else if (percentSpacing) { + if (scale) { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_1 = Math.sqrt(x * x + y * y); + lengths[i] = length_1; + } + spaces[++i] = spacing; + } + else { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_2 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_2; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_2 / setupLength; + } + } + } + else { + for (var i = 1; i < spacesCount; i++) + spaces[i] = spacing; + } + var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, percentSpacing); + var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + var tip = false; + if (offsetRotation == 0) + tip = rotateMode == spine.RotateMode.Chain; + else { + tip = false; + var p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + } + for (var i = 0, p = 3; i < boneCount; i++, p += 3) { + var bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; + var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + var length_3 = lengths[i]; + if (length_3 != 0) { + var s = (Math.sqrt(dx * dx + dy * dy) / length_3 - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (rotate) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + var length_4 = bone.data.length; + boneX += (length_4 * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length_4 * (sin * a + cos * c) - dy) * rotateMix; + } + else { + r += offsetRotation; + } + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.appliedValid = false; + } + }; + PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) { + var target = this.target; + var position = this.position; + var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + var closed = path.closed; + var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; + if (!path.constantSpeed) { + var lengths = path.lengths; + curveCount -= closed ? 1 : 2; + var pathLength_1 = lengths[curveCount]; + if (percentPosition) + position *= pathLength_1; + if (percentSpacing) { + for (var i = 1; i < spacesCount; i++) + spaces[i] *= pathLength_1; + } + world = spine.Utils.setArraySize(this.world, 8); + for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength_1; + if (p < 0) + p += pathLength_1; + curve = 0; + } + else if (p < 0) { + if (prevCurve != PathConstraint.BEFORE) { + prevCurve = PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength_1) { + if (prevCurve != PathConstraint.AFTER) { + prevCurve = PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength_1, world, 0, out, o); + continue; + } + for (;; curve++) { + var length_5 = lengths[curve]; + if (p > length_5) + continue; + if (curve == 0) + p /= length_5; + else { + var prev = lengths[curve - 1]; + p = (p - prev) / (length_5 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } + else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); + } + return out; + } + if (closed) { + verticesLength += 2; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else { + curveCount--; + verticesLength -= 4; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + var curves = spine.Utils.setArraySize(this.curves, curveCount); + var pathLength = 0; + var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (var i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (percentPosition) + position *= pathLength; + else + position *= pathLength / path.lengths[curveCount - 1]; + if (percentSpacing) { + for (var i = 1; i < spacesCount; i++) + spaces[i] *= pathLength; + } + var segments = this.segments; + var curveLength = 0; + for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } + else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (;; curve++) { + var length_6 = curves[curve]; + if (p > length_6) + continue; + if (curve == 0) + p /= length_6; + else { + var prev = curves[curve - 1]; + p = (p - prev) / (length_6 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + var ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (;; segment++) { + var length_7 = segments[segment]; + if (p > length_7) + continue; + if (segment == 0) + p /= length_7; + else { + var prev = segments[segment - 1]; + p = segment + (p - prev) / (length_7 - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + } + return out; + }; + PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) { + var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) { + var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 0.001) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + }; + PathConstraint.prototype.getOrder = function () { + return this.data.order; + }; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + PathConstraint.epsilon = 0.00001; + return PathConstraint; + }()); + spine.PathConstraint = PathConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraintData = (function () { + function PathConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.name = name; + } + return PathConstraintData; + }()); + spine.PathConstraintData = PathConstraintData; + var PositionMode; + (function (PositionMode) { + PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; + PositionMode[PositionMode["Percent"] = 1] = "Percent"; + })(PositionMode = spine.PositionMode || (spine.PositionMode = {})); + var SpacingMode; + (function (SpacingMode) { + SpacingMode[SpacingMode["Length"] = 0] = "Length"; + SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; + SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; + })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {})); + var RotateMode; + (function (RotateMode) { + RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; + RotateMode[RotateMode["Chain"] = 1] = "Chain"; + RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; + })(RotateMode = spine.RotateMode || (spine.RotateMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Assets = (function () { + function Assets(clientId) { + this.toLoad = new Array(); + this.assets = {}; + this.clientId = clientId; + } + Assets.prototype.loaded = function () { + var i = 0; + for (var v in this.assets) + i++; + return i; + }; + return Assets; + }()); + var SharedAssetManager = (function () { + function SharedAssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.clientAssets = {}; + this.queuedAssets = {}; + this.rawAssets = {}; + this.errors = {}; + this.pathPrefix = pathPrefix; + } + SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) { + clientAssets = new Assets(clientId); + this.clientAssets[clientId] = clientAssets; + } + if (textureLoader !== null) + clientAssets.textureLoader = textureLoader; + clientAssets.toLoad.push(path); + if (this.queuedAssets[path] === path) { + return false; + } + else { + this.queuedAssets[path] = path; + return true; + } + }; + SharedAssetManager.prototype.loadText = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = request.responseText; + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadJson = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = JSON.parse(request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, textureLoader, path)) + return; + var img = new Image(); + img.src = path; + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + _this.rawAssets[path] = img; + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + }; + }; + SharedAssetManager.prototype.get = function (clientId, path) { + path = this.pathPrefix + path; + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + return clientAssets.assets[path]; + }; + SharedAssetManager.prototype.updateClientAssets = function (clientAssets) { + for (var i = 0; i < clientAssets.toLoad.length; i++) { + var path = clientAssets.toLoad[i]; + var asset = clientAssets.assets[path]; + if (asset === null || asset === undefined) { + var rawAsset = this.rawAssets[path]; + if (rawAsset === null || rawAsset === undefined) + continue; + if (rawAsset instanceof HTMLImageElement) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + } + }; + SharedAssetManager.prototype.isLoadingComplete = function (clientId) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + this.updateClientAssets(clientAssets); + return clientAssets.toLoad.length == clientAssets.loaded(); + }; + SharedAssetManager.prototype.dispose = function () { + }; + SharedAssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + SharedAssetManager.prototype.getErrors = function () { + return this.errors; + }; + return SharedAssetManager; + }()); + spine.SharedAssetManager = SharedAssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skeleton = (function () { + function Skeleton(data) { + this._updateCache = new Array(); + this.updateCacheReset = new Array(); + this.time = 0; + this.scaleX = 1; + this.scaleY = 1; + this.x = 0; + this.y = 0; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) { + var boneData = data.bones[i]; + var bone = void 0; + if (boneData.parent == null) + bone = new spine.Bone(boneData, this, null); + else { + var parent_1 = this.bones[boneData.parent.index]; + bone = new spine.Bone(boneData, this, parent_1); + parent_1.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (var i = 0; i < data.slots.length; i++) { + var slotData = data.slots[i]; + var bone = this.bones[slotData.boneData.index]; + var slot = new spine.Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (var i = 0; i < data.ikConstraints.length; i++) { + var ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (var i = 0; i < data.transformConstraints.length; i++) { + var transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (var i = 0; i < data.pathConstraints.length; i++) { + var pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this)); + } + this.color = new spine.Color(1, 1, 1, 1); + this.updateCache(); + } + Skeleton.prototype.updateCache = function () { + var updateCache = this._updateCache; + updateCache.length = 0; + this.updateCacheReset.length = 0; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].sorted = false; + var ikConstraints = this.ikConstraints; + var transformConstraints = this.transformConstraints; + var pathConstraints = this.pathConstraints; + var ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + var constraintCount = ikCount + transformCount + pathCount; + outer: for (var i = 0; i < constraintCount; i++) { + for (var ii = 0; ii < ikCount; ii++) { + var constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < transformCount; ii++) { + var constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < pathCount; ii++) { + var constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (var i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + }; + Skeleton.prototype.sortIkConstraint = function (constraint) { + var target = constraint.target; + this.sortBone(target); + var constrained = constraint.bones; + var parent = constrained[0]; + this.sortBone(parent); + if (constrained.length > 1) { + var child = constrained[constrained.length - 1]; + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + this._updateCache.push(constraint); + this.sortReset(parent.children); + constrained[constrained.length - 1].sorted = true; + }; + Skeleton.prototype.sortPathConstraint = function (constraint) { + var slot = constraint.target; + var slotIndex = slot.data.index; + var slotBone = slot.bone; + if (this.skin != null) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (var i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + var attachment = slot.getAttachment(); + if (attachment instanceof spine.PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (var i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (var i = 0; i < boneCount; i++) + constrained[i].sorted = true; + }; + Skeleton.prototype.sortTransformConstraint = function (constraint) { + this.sortBone(constraint.target); + var constrained = constraint.bones; + var boneCount = constrained.length; + if (constraint.data.local) { + for (var i = 0; i < boneCount; i++) { + var child = constrained[i]; + this.sortBone(child.parent); + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + } + else { + for (var i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + }; + Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) { + var attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (var key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + }; + Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) { + if (!(attachment instanceof spine.PathAttachment)) + return; + var pathBones = attachment.bones; + if (pathBones == null) + this.sortBone(slotBone); + else { + var bones = this.bones; + var i = 0; + while (i < pathBones.length) { + var boneCount = pathBones[i++]; + for (var n = i + boneCount; i < n; i++) { + var boneIndex = pathBones[i]; + this.sortBone(bones[boneIndex]); + } + } + } + }; + Skeleton.prototype.sortBone = function (bone) { + if (bone.sorted) + return; + var parent = bone.parent; + if (parent != null) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + }; + Skeleton.prototype.sortReset = function (bones) { + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + }; + Skeleton.prototype.updateWorldTransform = function () { + var updateCacheReset = this.updateCacheReset; + for (var i = 0, n = updateCacheReset.length; i < n; i++) { + var bone = updateCacheReset[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + var updateCache = this._updateCache; + for (var i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + }; + Skeleton.prototype.setToSetupPose = function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }; + Skeleton.prototype.setBonesToSetupPose = function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + } + }; + Skeleton.prototype.setSlotsToSetupPose = function () { + var slots = this.slots; + spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + }; + Skeleton.prototype.getRootBone = function () { + if (this.bones.length == 0) + return null; + return this.bones[0]; + }; + Skeleton.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + }; + Skeleton.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) + return i; + return -1; + }; + Skeleton.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + }; + Skeleton.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) + return i; + return -1; + }; + Skeleton.prototype.setSkinByName = function (skinName) { + var skin = this.data.findSkin(skinName); + if (skin == null) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + }; + Skeleton.prototype.setSkin = function (newSkin) { + if (newSkin != null) { + if (this.skin != null) + newSkin.attachAll(this, this.skin); + else { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var name_1 = slot.data.attachmentName; + if (name_1 != null) { + var attachment = newSkin.getAttachment(i, name_1); + if (attachment != null) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + }; + Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) { + return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName); + }; + Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) { + if (attachmentName == null) + throw new Error("attachmentName cannot be null."); + if (this.skin != null) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + return attachment; + } + if (this.data.defaultSkin != null) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }; + Skeleton.prototype.setAttachment = function (slotName, attachmentName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName != null) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + }; + Skeleton.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + }; + Skeleton.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.getBounds = function (offset, size, temp) { + if (temp === void 0) { temp = new Array(2); } + if (offset == null) + throw new Error("offset cannot be null."); + if (size == null) + throw new Error("size cannot be null."); + var drawOrder = this.drawOrder; + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var verticesLength = 0; + var vertices = null; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) { + verticesLength = 8; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices != null) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { + var x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + }; + Skeleton.prototype.update = function (delta) { + this.time += delta; + }; + return Skeleton; + }()); + spine.Skeleton = Skeleton; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBounds = (function () { + function SkeletonBounds() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new spine.Pool(function () { + return spine.Utils.newFloatArray(16); + }); + } + SkeletonBounds.prototype.update = function (skeleton, updateAabb) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + var boundingBoxes = this.boundingBoxes; + var polygons = this.polygons; + var polygonPool = this.polygonPool; + var slots = skeleton.slots; + var slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (var i = 0; i < slotCount; i++) { + var slot = slots[i]; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.BoundingBoxAttachment) { + var boundingBox = attachment; + boundingBoxes.push(boundingBox); + var polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } + else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + }; + SkeletonBounds.prototype.aabbCompute = function () { + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + var vertices = polygon; + for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) { + var x = vertices[ii]; + var y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + }; + SkeletonBounds.prototype.aabbContainsPoint = function (x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + }; + SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) { + var minX = this.minX; + var minY = this.minY; + var maxX = this.maxX; + var maxY = this.maxY; + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + return false; + var m = (y2 - y1) / (x2 - x1); + var y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + var x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + }; + SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + }; + SkeletonBounds.prototype.containsPoint = function (x, y) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) { + var vertices = polygon; + var nn = polygon.length; + var prevIndex = nn - 2; + var inside = false; + for (var ii = 0; ii < nn; ii += 2) { + var vertexY = vertices[ii + 1]; + var prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + var vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + }; + SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) { + var vertices = polygon; + var nn = polygon.length; + var width12 = x1 - x2, height12 = y1 - y2; + var det1 = x1 * y2 - y1 * x2; + var x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (var ii = 0; ii < nn; ii += 2) { + var x4 = vertices[ii], y4 = vertices[ii + 1]; + var det2 = x3 * y4 - y3 * x4; + var width34 = x3 - x4, height34 = y3 - y4; + var det3 = width12 * height34 - height12 * width34; + var x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + var y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + }; + SkeletonBounds.prototype.getPolygon = function (boundingBox) { + if (boundingBox == null) + throw new Error("boundingBox cannot be null."); + var index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + }; + SkeletonBounds.prototype.getWidth = function () { + return this.maxX - this.minX; + }; + SkeletonBounds.prototype.getHeight = function () { + return this.maxY - this.minY; + }; + return SkeletonBounds; + }()); + spine.SkeletonBounds = SkeletonBounds; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonClipping = (function () { + function SkeletonClipping() { + this.triangulator = new spine.Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + SkeletonClipping.prototype.clipStart = function (slot, clip) { + if (this.clipAttachment != null) + return 0; + this.clipAttachment = clip; + var n = clip.worldVerticesLength; + var vertices = spine.Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + var clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) { + var polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + }; + SkeletonClipping.prototype.clipEndWithSlot = function (slot) { + if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + }; + SkeletonClipping.prototype.clipEnd = function () { + if (this.clipAttachment == null) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + }; + SkeletonClipping.prototype.isClipping = function () { + return this.clipAttachment != null; + }; + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + var clippedTriangles = this.clippedTriangles; + var polygons = this.clippingPolygons; + var polygonsCount = this.clippingPolygons.length; + var vertexSize = twoColor ? 12 : 8; + var index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: for (var i = 0; i < trianglesLength; i += 3) { + var vertexOffset = triangles[i] << 1; + var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { + var s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + var clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + var d = 1 / (d0 * d2 + d1 * (y1 - y3)); + var clipOutputCount = clipOutputLength >> 1; + var clipOutputItems = this.clipOutput; + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (var ii = 0; ii < clipOutputLength; ii += 2) { + var x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + var c0 = x - x3, c1 = y - y3; + var a = (d0 * c0 + d1 * c1) * d; + var b = (d4 * c0 + d2 * c1) * d; + var c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (var ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + ii); + clippedTrianglesItems[s + 2] = (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } + else { + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } + else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + 1); + clippedTrianglesItems[s + 2] = (index + 2); + index += 3; + continue outer; + } + } + } + }; + SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) { + var originalOutput = output; + var clipped = false; + var input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } + else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + var clippingVertices = clippingArea; + var clippingVerticesLast = clippingArea.length - 4; + for (var i = 0;; i += 2) { + var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + var inputVertices = input; + var inputVerticesLength = input.length - 2, outputStart = output.length; + for (var ii = 0; ii < inputVerticesLength; ii += 2) { + var inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 0.000001) { + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else { + output.push(edgeX); + output.push(edgeY); + } + } + else if (side2) { + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 0.000001) { + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else { + output.push(edgeX); + output.push(edgeY); + } + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + var temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (var i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } + else + originalOutput.length = originalOutput.length - 2; + return clipped; + }; + SkeletonClipping.makeClockwise = function (polygon) { + var vertices = polygon; + var verticeslength = polygon.length; + var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (var i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + var x = vertices[i], y = vertices[i + 1]; + var other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + }; + return SkeletonClipping; + }()); + spine.SkeletonClipping = SkeletonClipping; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonData = (function () { + function SkeletonData() { + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + this.fps = 0; + } + SkeletonData.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + }; + SkeletonData.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) + return i; + return -1; + }; + SkeletonData.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + }; + SkeletonData.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) + return i; + return -1; + }; + SkeletonData.prototype.findSkin = function (skinName) { + if (skinName == null) + throw new Error("skinName cannot be null."); + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) { + var skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + }; + SkeletonData.prototype.findEvent = function (eventDataName) { + if (eventDataName == null) + throw new Error("eventDataName cannot be null."); + var events = this.events; + for (var i = 0, n = events.length; i < n; i++) { + var event_4 = events[i]; + if (event_4.name == eventDataName) + return event_4; + } + return null; + }; + SkeletonData.prototype.findAnimation = function (animationName) { + if (animationName == null) + throw new Error("animationName cannot be null."); + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) { + var animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + }; + SkeletonData.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) { + if (pathConstraintName == null) + throw new Error("pathConstraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) + if (pathConstraints[i].name == pathConstraintName) + return i; + return -1; + }; + return SkeletonData; + }()); + spine.SkeletonData = SkeletonData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonJson = (function () { + function SkeletonJson(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonJson.prototype.readSkeletonData = function (json) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + var root = typeof (json) === "string" ? JSON.parse(json) : json; + var skeletonMap = root.skeleton; + if (skeletonMap != null) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (var i = 0; i < root.bones.length; i++) { + var boneMap = root.bones[i]; + var parent_2 = null; + var parentName = this.getValue(boneMap, "parent", null); + if (parentName != null) { + parent_2 = skeletonData.findBone(parentName); + if (parent_2 == null) + throw new Error("Parent bone not found: " + parentName); + } + var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_2); + data.length = this.getValue(boneMap, "length", 0) * scale; + data.x = this.getValue(boneMap, "x", 0) * scale; + data.y = this.getValue(boneMap, "y", 0) * scale; + data.rotation = this.getValue(boneMap, "rotation", 0); + data.scaleX = this.getValue(boneMap, "scaleX", 1); + data.scaleY = this.getValue(boneMap, "scaleY", 1); + data.shearX = this.getValue(boneMap, "shearX", 0); + data.shearY = this.getValue(boneMap, "shearY", 0); + data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, "transform", "normal")); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (var i = 0; i < root.slots.length; i++) { + var slotMap = root.slots[i]; + var slotName = slotMap.name; + var boneName = slotMap.bone; + var boneData = skeletonData.findBone(boneName); + if (boneData == null) + throw new Error("Slot bone not found: " + boneName); + var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData); + var color = this.getValue(slotMap, "color", null); + if (color != null) + data.color.setFromString(color); + var dark = this.getValue(slotMap, "dark", null); + if (dark != null) { + data.darkColor = new spine.Color(1, 1, 1, 1); + data.darkColor.setFromString(dark); + } + data.attachmentName = this.getValue(slotMap, "attachment", null); + data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (var i = 0; i < root.ik.length; i++) { + var constraintMap = root.ik[i]; + var data = new spine.IkConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("IK bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("IK target bone not found: " + targetName); + data.mix = this.getValue(constraintMap, "mix", 1); + data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = this.getValue(constraintMap, "compress", false); + data.stretch = this.getValue(constraintMap, "stretch", false); + data.uniform = this.getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (var i = 0; i < root.transform.length; i++) { + var constraintMap = root.transform[i]; + var data = new spine.TransformConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("Transform constraint target bone not found: " + targetName); + data.local = this.getValue(constraintMap, "local", false); + data.relative = this.getValue(constraintMap, "relative", false); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.offsetX = this.getValue(constraintMap, "x", 0) * scale; + data.offsetY = this.getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0); + data.offsetShearY = this.getValue(constraintMap, "shearY", 0); + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + data.scaleMix = this.getValue(constraintMap, "scaleMix", 1); + data.shearMix = this.getValue(constraintMap, "shearMix", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (var i = 0; i < root.path.length; i++) { + var constraintMap = root.path[i]; + var data = new spine.PathConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + if (data.target == null) + throw new Error("Path target slot not found: " + targetName); + data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent")); + data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length")); + data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent")); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.position = this.getValue(constraintMap, "position", 0); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = this.getValue(constraintMap, "spacing", 0); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (var skinName in root.skins) { + var skinMap = root.skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + var slotMap = skinMap[slotName]; + for (var entryName in slotMap) { + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData); + if (attachment != null) + skin.addAttachment(slotIndex, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (var i = 0, n = this.linkedMeshes.length; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_3 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_3 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.setParentMesh(parent_3); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (var eventName in root.events) { + var eventMap = root.events[eventName]; + var data = new spine.EventData(eventName); + data.intValue = this.getValue(eventMap, "int", 0); + data.floatValue = this.getValue(eventMap, "float", 0); + data.stringValue = this.getValue(eventMap, "string", ""); + data.audioPath = this.getValue(eventMap, "audio", null); + if (data.audioPath != null) { + data.volume = this.getValue(eventMap, "volume", 1); + data.balance = this.getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (var animationName in root.animations) { + var animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + }; + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) { + var scale = this.scale; + name = this.getValue(map, "name", name); + var type = this.getValue(map, "type", "region"); + switch (type) { + case "region": { + var path = this.getValue(map, "path", name); + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = this.getValue(map, "x", 0) * scale; + region.y = this.getValue(map, "y", 0) * scale; + region.scaleX = this.getValue(map, "scaleX", 1); + region.scaleY = this.getValue(map, "scaleY", 1); + region.rotation = this.getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + var color = this.getValue(map, "color", null); + if (color != null) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + this.readVertices(map, box, map.vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + var path = this.getValue(map, "path", name); + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + var color = this.getValue(map, "color", null); + if (color != null) + mesh.color.setFromString(color); + var parent_4 = this.getValue(map, "parent", null); + if (parent_4 != null) { + mesh.inheritDeform = this.getValue(map, "deform", true); + this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_4)); + return mesh; + } + var uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = this.getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = this.getValue(map, "closed", false); + path.constantSpeed = this.getValue(map, "constantSpeed", true); + var vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + var color = this.getValue(map, "color", null); + if (color != null) + path.color.setFromString(color); + return path; + } + case "point": { + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = this.getValue(map, "x", 0) * scale; + point.y = this.getValue(map, "y", 0) * scale; + point.rotation = this.getValue(map, "rotation", 0); + var color = this.getValue(map, "color", null); + if (color != null) + point.color.setFromString(color); + return point; + } + case "clipping": { + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + var end = this.getValue(map, "end", null); + if (end != null) { + var slot = skeletonData.findSlot(end); + if (slot == null) + throw new Error("Clipping end slot not found: " + end); + clip.endSlot = slot; + } + var vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + clip.color.setFromString(color); + return clip; + } + } + return null; + }; + SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) { + var scale = this.scale; + attachment.worldVerticesLength = verticesLength; + var vertices = map.vertices; + if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); + if (scale != 1) { + for (var i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + var weights = new Array(); + var bones = new Array(); + for (var i = 0, n = vertices.length; i < n;) { + var boneCount = vertices[i++]; + bones.push(boneCount); + for (var nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = spine.Utils.toFloatArray(weights); + }; + SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) { + var scale = this.scale; + var timelines = new Array(); + var duration = 0; + if (map.slots) { + for (var slotName in map.slots) { + var slotMap = map.slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else if (timelineName == "color") { + var timeline = new spine.ColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var color = new spine.Color(); + color.setFromString(valueMap.color); + timeline.setFrame(frameIndex, valueMap.time, color.r, color.g, color.b, color.a); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); + } + else if (timelineName == "twoColor") { + var timeline = new spine.TwoColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var light = new spine.Color(); + var dark = new spine.Color(); + light.setFromString(valueMap.light); + dark.setFromString(valueMap.dark); + timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + if (map.bones) { + for (var boneName in map.bones) { + var boneMap = map.bones[boneName]; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) + throw new Error("Bone not found: " + boneName); + for (var timelineName in boneMap) { + var timelineMap = boneMap[timelineName]; + if (timelineName === "rotate") { + var timeline = new spine.RotateTimeline(timelineMap.length); + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, valueMap.angle); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]); + } + else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "scale") + timeline = new spine.ScaleTimeline(timelineMap.length); + else if (timelineName === "shear") + timeline = new spine.ShearTimeline(timelineMap.length); + else { + timeline = new spine.TranslateTimeline(timelineMap.length); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var x = this.getValue(valueMap, "x", 0), y = this.getValue(valueMap, "y", 0); + timeline.setFrame(frameIndex, valueMap.time, x * timelineScale, y * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); + } + } + } + if (map.ik) { + for (var constraintName in map.ik) { + var constraintMap = map.ik[constraintName]; + var constraint = skeletonData.findIkConstraint(constraintName); + var timeline = new spine.IkConstraintTimeline(constraintMap.length); + timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "compress", false), this.getValue(valueMap, "stretch", false)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + } + if (map.transform) { + for (var constraintName in map.transform) { + var constraintMap = map.transform[constraintName]; + var constraint = skeletonData.findTransformConstraint(constraintName); + var timeline = new spine.TransformConstraintTimeline(constraintMap.length); + timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + } + if (map.paths) { + for (var constraintName in map.paths) { + var constraintMap = map.paths[constraintName]; + var index = skeletonData.findPathConstraintIndex(constraintName); + if (index == -1) + throw new Error("Path constraint not found: " + constraintName); + var data = skeletonData.pathConstraints[index]; + for (var timelineName in constraintMap) { + var timelineMap = constraintMap[timelineName]; + if (timelineName === "position" || timelineName === "spacing") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "spacing") { + timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(timelineMap.length); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, timelineName, 0) * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + } + else if (timelineName === "mix") { + var timeline = new spine.PathConstraintMixTimeline(timelineMap.length); + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + } + } + } + } + if (map.deform) { + for (var deformName in map.deform) { + var deformMap = map.deform[deformName]; + var skin = skeletonData.findSkin(deformName); + if (skin == null) + throw new Error("Skin not found: " + deformName); + for (var slotName in deformMap) { + var slotMap = deformMap[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotMap.name); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + var attachment = skin.getAttachment(slotIndex, timelineName); + if (attachment == null) + throw new Error("Deform attachment not found: " + timelineMap.name); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var timeline = new spine.DeformTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + var frameIndex = 0; + for (var j = 0; j < timelineMap.length; j++) { + var valueMap = timelineMap[j]; + var deform = void 0; + var verticesValue = this.getValue(valueMap, "vertices", null); + if (verticesValue == null) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = this.getValue(valueMap, "offset", 0); + spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (var i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (var i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frameIndex, valueMap.time, deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_5 = new spine.Event(spine.Utils.toSinglePrecision(eventMap.time), eventData); + event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + if (event_5.data.audioPath != null) { + event_5.volume = this.getValue(eventMap, "volume", 1); + event_5.balance = this.getValue(eventMap, "balance", 0); + } + timeline.setFrame(frameIndex++, event_5); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.curve) + return; + if (map.curve === "stepped") + timeline.setStepped(frameIndex); + else if (Object.prototype.toString.call(map.curve) === '[object Array]') { + var curve = map.curve; + timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + SkeletonJson.transformModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.TransformMode.Normal; + if (str == "onlytranslation") + return spine.TransformMode.OnlyTranslation; + if (str == "norotationorreflection") + return spine.TransformMode.NoRotationOrReflection; + if (str == "noscale") + return spine.TransformMode.NoScale; + if (str == "noscaleorreflection") + return spine.TransformMode.NoScaleOrReflection; + throw new Error("Unknown transform mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.addAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.attachmentVertices = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.darkColor = data.darkColor == null ? null : new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.attachmentVertices.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.darkColor != null) + this.darkColor.setFromColor(this.data.darkColor); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + var TextureFilter; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {})); + var TextureWrap; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {})); + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; + var FakeTexture = (function (_super) { + __extends(FakeTexture, _super); + function FakeTexture() { + return _super !== null && _super.apply(this, arguments) || this; + } + FakeTexture.prototype.setFilters = function (minFilter, magFilter) { }; + FakeTexture.prototype.setWraps = function (uWrap, vWrap) { }; + FakeTexture.prototype.dispose = function () { }; + return FakeTexture; + }(Texture)); + spine.FakeTexture = FakeTexture; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + region.rotate = reader.readValue() == "true"; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + return _super !== null && _super.apply(this, arguments) || this; + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } + else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + }; + TransformConstraint.prototype.applyAbsoluteWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect; + var offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; + bone.a *= s; + bone.c *= s; + s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyRelativeWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * translateMix; + bone.worldY += temp.y * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + var b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyAbsoluteLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) { + var r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + var shearY = bone.ashearY; + if (shearMix != 0) { + var r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.applyRelativeLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) + rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001) + scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) + scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + var shearY = bone.ashearY; + if (shearMix != 0) + shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.getOrder = function () { + return this.data.order; + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function () { + function TransformConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + this.relative = false; + this.local = false; + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return TransformConstraintData; + }()); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Triangulator = (function () { + function Triangulator() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new spine.Pool(function () { + return new Array(); + }); + this.polygonIndicesPool = new spine.Pool(function () { + return new Array(); + }); + } + Triangulator.prototype.triangulate = function (verticesArray) { + var vertices = verticesArray; + var vertexCount = verticesArray.length >> 1; + var indices = this.indicesArray; + indices.length = 0; + for (var i = 0; i < vertexCount; i++) + indices[i] = i; + var isConcave = this.isConcaveArray; + isConcave.length = 0; + for (var i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + var triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + var previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: if (!isConcave[i]) { + var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + var p1x = vertices[p1], p1y = vertices[p1 + 1]; + var p2x = vertices[p2], p2y = vertices[p2 + 1]; + var p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + var v = indices[ii] << 1; + var vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + var previousIndex = (vertexCount + i - 1) % vertexCount; + var nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + }; + Triangulator.prototype.decompose = function (verticesArray, triangles) { + var vertices = verticesArray; + var convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + var convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + var polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + var polygon = this.polygonPool.obtain(); + polygon.length = 0; + var fanBaseIndex = -1, lastWinding = 0; + for (var i = 0, n = triangles.length; i < n; i += 3) { + var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + var x1 = vertices[t1], y1 = vertices[t1 + 1]; + var x2 = vertices[t2], y2 = vertices[t2 + 1]; + var x3 = vertices[t3], y3 = vertices[t3 + 1]; + var merged = false; + if (fanBaseIndex == t1) { + var o = polygon.length - 4; + var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (var i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + var firstIndex = polygonIndices[0]; + var lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + var o = polygon.length - 4; + var prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + var prevX = polygon[o + 2], prevY = polygon[o + 3]; + var firstX = polygon[0], firstY = polygon[1]; + var secondX = polygon[2], secondY = polygon[3]; + var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (var ii = 0; ii < n; ii++) { + if (ii == i) + continue; + var otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + var otherFirstIndex = otherIndices[0]; + var otherSecondIndex = otherIndices[1]; + var otherLastIndex = otherIndices[2]; + var otherPoly = convexPolygons[ii]; + var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (var i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + }; + Triangulator.isConcave = function (index, vertexCount, vertices, indices) { + var previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + var current = indices[index] << 1; + var next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); + }; + Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + }; + Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) { + var px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + }; + return Triangulator; + }()); + spine.Triangulator = Triangulator; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IntSet = (function () { + function IntSet() { + this.array = new Array(); + } + IntSet.prototype.add = function (value) { + var contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + }; + IntSet.prototype.contains = function (value) { + return this.array[value | 0] != undefined; + }; + IntSet.prototype.remove = function (value) { + this.array[value | 0] = undefined; + }; + IntSet.prototype.clear = function () { + this.array.length = 0; + }; + return IntSet; + }()); + spine.IntSet = IntSet; + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + }; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + }; + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + }; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; + }()); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { + } + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); + }; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); + }; + MathUtils.signum = function (value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + }; + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + }; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + }; + MathUtils.randomTriangular = function (min, max) { + return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + }; + MathUtils.randomTriangularWith = function (min, max, mode) { + var u = Math.random(); + var d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + }; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; + }()); + spine.MathUtils = MathUtils; + var Interpolation = (function () { + function Interpolation() { + } + Interpolation.prototype.apply = function (start, end, a) { + return start + (end - start) * this.applyInternal(a); + }; + return Interpolation; + }()); + spine.Interpolation = Interpolation; + var Pow = (function (_super) { + __extends(Pow, _super); + function Pow(power) { + var _this = _super.call(this) || this; + _this.power = 2; + _this.power = power; + return _this; + } + Pow.prototype.applyInternal = function (a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + }; + return Pow; + }(Interpolation)); + spine.Pow = Pow; + var PowOut = (function (_super) { + __extends(PowOut, _super); + function PowOut(power) { + return _super.call(this, power) || this; + } + PowOut.prototype.applyInternal = function (a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + }; + return PowOut; + }(Pow)); + spine.PowOut = PowOut; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; + } + return array; + }; + Utils.ensureArrayCapacity = function (array, size, value) { + if (value === void 0) { value = 0; } + if (array.length >= size) + return array; + return Utils.setArraySize(array, size, value); + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.newShortArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Int16Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.toSinglePrecision = function (value) { + return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + }; + Utils.webkit602BugfixHelper = function (alpha, blend) { + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; + }()); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { + } + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + }; + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + }; + Pool.prototype.free = function (item) { + if (item.reset) + item.reset(); + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) { + if (items[i].reset) + items[i].reset(); + this.items[i] = items[i]; + } + }; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; + }()); + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; + } + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; + }()); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; + } + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + }; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; + var WindowedMean = (function () { + function WindowedMean(windowSize) { + if (windowSize === void 0) { windowSize = 32; } + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + WindowedMean.prototype.hasEnoughData = function () { + return this.addedValues >= this.values.length; + }; + WindowedMean.prototype.addValue = function (value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + }; + WindowedMean.prototype.getMean = function () { + if (this.hasEnoughData()) { + if (this.dirty) { + var mean = 0; + for (var i = 0; i < this.values.length; i++) { + mean += this.values[i]; + } + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + else { + return 0; + } + }; + return WindowedMean; + }()); + spine.WindowedMean = WindowedMean; +})(spine || (spine = {})); +(function () { + if (!Math.fround) { + Math.fround = (function (array) { + return function (x) { + return array[0] = x, array[0]; + }; + })(new Float32Array(1)); + } +})(); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + var _this = _super.call(this, name) || this; + _this.id = (VertexAttachment.nextID++ & 65535) << 11; + _this.worldVerticesLength = 0; + return _this; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + var skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; + }; + VertexAttachment.nextID = 0; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AttachmentType; + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + AttachmentType[AttachmentType["Point"] = 5] = "Point"; + })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var ClippingAttachment = (function (_super) { + __extends(ClippingAttachment, _super); + function ClippingAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1); + return _this; + } + return ClippingAttachment; + }(spine.VertexAttachment)); + spine.ClippingAttachment = ClippingAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + _this.inheritDeform = false; + _this.tempColor = new spine.Color(0, 0, 0, 0); + return _this; + } + MeshAttachment.prototype.updateUVs = function () { + var regionUVs = this.regionUVs; + if (this.uvs == null || this.uvs.length != regionUVs.length) + this.uvs = spine.Utils.newFloatArray(regionUVs.length); + var uvs = this.uvs; + var u = 0, v = 0, width = 0, height = 0; + if (this.region instanceof spine.TextureAtlasRegion) { + var region = this.region; + var textureWidth = region.texture.getImage().width, textureHeight = region.texture.getImage().height; + if (region.rotate) { + u = region.u - (region.originalHeight - region.offsetY - region.height) / textureWidth; + v = region.v - (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + height - regionUVs[i] * height; + } + return; + } + u = region.u - region.offsetX / textureWidth; + v = region.v - (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } + else if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + }; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + var _this = _super.call(this, name) || this; + _this.closed = false; + _this.constantSpeed = false; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PointAttachment = (function (_super) { + __extends(PointAttachment, _super); + function PointAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.38, 0.94, 0, 1); + return _this; + } + PointAttachment.prototype.computeWorldPosition = function (bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + }; + PointAttachment.prototype.computeWorldRotation = function (bone) { + var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation); + var x = cos * bone.a + sin * bone.b; + var y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * spine.MathUtils.radDeg; + }; + return PointAttachment; + }(spine.VertexAttachment)); + spine.PointAttachment = PointAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + var _this = _super.call(this, name) || this; + _this.x = 0; + _this.y = 0; + _this.scaleX = 1; + _this.scaleY = 1; + _this.rotation = 0; + _this.width = 0; + _this.height = 0; + _this.color = new spine.Color(1, 1, 1, 1); + _this.offset = spine.Utils.newFloatArray(8); + _this.uvs = spine.Utils.newFloatArray(8); + _this.tempColor = new spine.Color(1, 1, 1, 1); + return _this; + } + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.setRegion = function (region) { + this.region = region; + var uvs = this.uvs; + if (region.rotate) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; + } + else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + }; + RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) { + var vertexOffset = this.offset; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = vertexOffset[RegionAttachment.OX1]; + offsetY = vertexOffset[RegionAttachment.OY1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX2]; + offsetY = vertexOffset[RegionAttachment.OY2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX3]; + offsetY = vertexOffset[RegionAttachment.OY3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX4]; + offsetY = vertexOffset[RegionAttachment.OY4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + }; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var JitterEffect = (function () { + function JitterEffect(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; + } + JitterEffect.prototype.begin = function (skeleton) { + }; + JitterEffect.prototype.transform = function (position, uv, light, dark) { + position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + }; + JitterEffect.prototype.end = function () { + }; + return JitterEffect; + }()); + spine.JitterEffect = JitterEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SwirlEffect = (function () { + function SwirlEffect(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; + } + SwirlEffect.prototype.begin = function (skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + }; + SwirlEffect.prototype.transform = function (position, uv, light, dark) { + var radAngle = this.angle * spine.MathUtils.degreesToRadians; + var x = position.x - this.worldX; + var y = position.y - this.worldY; + var dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + var cos = Math.cos(theta); + var sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + }; + SwirlEffect.prototype.end = function () { + }; + SwirlEffect.interpolation = new spine.PowOut(2); + return SwirlEffect; + }()); + spine.SwirlEffect = SwirlEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + return _super.call(this, function (image) { return new spine.canvas.CanvasTexture(image); }, pathPrefix) || this; + } + return AssetManager; + }(spine.AssetManager)); + canvas.AssetManager = AssetManager; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var CanvasTexture = (function (_super) { + __extends(CanvasTexture, _super); + function CanvasTexture(image) { + return _super.call(this, image) || this; + } + CanvasTexture.prototype.setFilters = function (minFilter, magFilter) { }; + CanvasTexture.prototype.setWraps = function (uWrap, vWrap) { }; + CanvasTexture.prototype.dispose = function () { }; + return CanvasTexture; + }(spine.Texture)); + canvas.CanvasTexture = CanvasTexture; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var SkeletonRenderer = (function () { + function SkeletonRenderer(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.vertices = spine.Utils.newFloatArray(8 * 1024); + this.tempColor = new spine.Color(); + this.ctx = context; + } + SkeletonRenderer.prototype.draw = function (skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + }; + SkeletonRenderer.prototype.drawImages = function (skeleton) { + var ctx = this.ctx; + var drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + ctx.save(); + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var regionAttachment = null; + var region = null; + var image = null; + if (attachment instanceof spine.RegionAttachment) { + regionAttachment = attachment; + region = regionAttachment.region; + image = region.texture.getImage(); + } + else + continue; + var skeleton_1 = slot.bone.skeleton; + var skeletonColor = skeleton_1.color; + var slotColor = slot.color; + var regionColor = regionAttachment.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, alpha); + var att = attachment; + var bone = slot.bone; + var w = region.width; + var h = region.height; + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + var atlasScale = att.width / w; + ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); + ctx.translate(w / 2, h / 2); + if (attachment.region.rotate) { + var t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + if (color.r != 1 || color.g != 1 || color.b != 1 || color.a != 1) { + ctx.globalAlpha = color.a; + } + ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + ctx.restore(); + }; + SkeletonRenderer.prototype.drawTriangles = function (skeleton) { + var blendMode = null; + var vertices = this.vertices; + var triangles = null; + var drawOrder = skeleton.drawOrder; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var texture = null; + var region = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.texture.getImage(); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture.getImage(); + } + else + continue; + if (texture != null) { + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + } + var skeleton_2 = slot.bone.skeleton; + var skeletonColor = skeleton_2.color; + var slotColor = slot.color; + var attachmentColor = attachment.color; + var alpha = skeletonColor.a * slotColor.a * attachmentColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha); + var ctx = this.ctx; + if (color.r != 1 || color.g != 1 || color.b != 1 || color.a != 1) { + ctx.globalAlpha = color.a; + } + for (var j = 0; j < triangles.length; j += 3) { + var t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + var x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + var x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + var 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + }; + SkeletonRenderer.prototype.drawTriangle = function (img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + var ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + }; + SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = region.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var vertices = this.vertices; + var uvs = region.uvs; + vertices[spine.RegionAttachment.C1R] = color.r; + vertices[spine.RegionAttachment.C1G] = color.g; + vertices[spine.RegionAttachment.C1B] = color.b; + vertices[spine.RegionAttachment.C1A] = color.a; + vertices[spine.RegionAttachment.U1] = uvs[0]; + vertices[spine.RegionAttachment.V1] = uvs[1]; + vertices[spine.RegionAttachment.C2R] = color.r; + vertices[spine.RegionAttachment.C2G] = color.g; + vertices[spine.RegionAttachment.C2B] = color.b; + vertices[spine.RegionAttachment.C2A] = color.a; + vertices[spine.RegionAttachment.U2] = uvs[2]; + vertices[spine.RegionAttachment.V2] = uvs[3]; + vertices[spine.RegionAttachment.C3R] = color.r; + vertices[spine.RegionAttachment.C3G] = color.g; + vertices[spine.RegionAttachment.C3B] = color.b; + vertices[spine.RegionAttachment.C3A] = color.a; + vertices[spine.RegionAttachment.U3] = uvs[4]; + vertices[spine.RegionAttachment.V3] = uvs[5]; + vertices[spine.RegionAttachment.C4R] = color.r; + vertices[spine.RegionAttachment.C4G] = color.g; + vertices[spine.RegionAttachment.C4B] = color.b; + vertices[spine.RegionAttachment.C4A] = color.a; + vertices[spine.RegionAttachment.U4] = uvs[6]; + vertices[spine.RegionAttachment.V4] = uvs[7]; + return vertices; + }; + SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = mesh.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + var numVertices = mesh.worldVerticesLength / 2; + if (this.vertices.length < mesh.worldVerticesLength) { + this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength); + } + var vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var uvs = mesh.uvs; + for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4; + return SkeletonRenderer; + }()); + canvas.SkeletonRenderer = SkeletonRenderer; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +//# sourceMappingURL=spine-canvas.js.map \ No newline at end of file diff --git a/release/MAC版本/lib/3.8/spine-canvas.js b/release/MAC版本/lib/3.8/spine-canvas.js new file mode 100644 index 0000000..033550c --- /dev/null +++ b/release/MAC版本/lib/3.8/spine-canvas.js @@ -0,0 +1,8472 @@ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var spine; +(function (spine) { + var Animation = (function () { + function Animation(name, timelines, duration) { + if (name == null) + throw new Error("name cannot be null."); + if (timelines == null) + throw new Error("timelines cannot be null."); + this.name = name; + this.timelines = timelines; + this.timelineIds = []; + for (var i = 0; i < timelines.length; i++) + this.timelineIds[timelines[i].getPropertyId()] = true; + this.duration = duration; + } + Animation.prototype.hasTimeline = function (id) { + return this.timelineIds[id] == true; + }; + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + }; + Animation.binarySearch = function (values, target, step) { + if (step === void 0) { step = 1; } + var low = 0; + var high = values.length / step - 2; + if (high == 0) + return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) + return (low + 1) * step; + current = (low + high) >>> 1; + } + }; + Animation.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) + return i; + return -1; + }; + return Animation; + }()); + spine.Animation = Animation; + var MixBlend; + (function (MixBlend) { + MixBlend[MixBlend["setup"] = 0] = "setup"; + MixBlend[MixBlend["first"] = 1] = "first"; + MixBlend[MixBlend["replace"] = 2] = "replace"; + MixBlend[MixBlend["add"] = 3] = "add"; + })(MixBlend = spine.MixBlend || (spine.MixBlend = {})); + var MixDirection; + (function (MixDirection) { + MixDirection[MixDirection["mixIn"] = 0] = "mixIn"; + MixDirection[MixDirection["mixOut"] = 1] = "mixOut"; + })(MixDirection = spine.MixDirection || (spine.MixDirection = {})); + var TimelineType; + (function (TimelineType) { + TimelineType[TimelineType["rotate"] = 0] = "rotate"; + TimelineType[TimelineType["translate"] = 1] = "translate"; + TimelineType[TimelineType["scale"] = 2] = "scale"; + TimelineType[TimelineType["shear"] = 3] = "shear"; + TimelineType[TimelineType["attachment"] = 4] = "attachment"; + TimelineType[TimelineType["color"] = 5] = "color"; + TimelineType[TimelineType["deform"] = 6] = "deform"; + TimelineType[TimelineType["event"] = 7] = "event"; + TimelineType[TimelineType["drawOrder"] = 8] = "drawOrder"; + TimelineType[TimelineType["ikConstraint"] = 9] = "ikConstraint"; + TimelineType[TimelineType["transformConstraint"] = 10] = "transformConstraint"; + TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; + TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; + TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; + TimelineType[TimelineType["twoColor"] = 14] = "twoColor"; + })(TimelineType = spine.TimelineType || (spine.TimelineType = {})); + var CurveTimeline = (function () { + function CurveTimeline(frameCount) { + if (frameCount <= 0) + throw new Error("frameCount must be > 0: " + frameCount); + this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE); + } + CurveTimeline.prototype.getFrameCount = function () { + return this.curves.length / CurveTimeline.BEZIER_SIZE + 1; + }; + CurveTimeline.prototype.setLinear = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR; + }; + CurveTimeline.prototype.setStepped = function (frameIndex) { + this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED; + }; + CurveTimeline.prototype.getCurveType = function (frameIndex) { + var index = frameIndex * CurveTimeline.BEZIER_SIZE; + if (index == this.curves.length) + return CurveTimeline.LINEAR; + var type = this.curves[index]; + if (type == CurveTimeline.LINEAR) + return CurveTimeline.LINEAR; + if (type == CurveTimeline.STEPPED) + return CurveTimeline.STEPPED; + return CurveTimeline.BEZIER; + }; + CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) { + var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03; + var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; + var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var curves = this.curves; + curves[i++] = CurveTimeline.BEZIER; + var x = dfx, y = dfy; + for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + }; + CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) { + percent = spine.MathUtils.clamp(percent, 0, 1); + var curves = this.curves; + var i = frameIndex * CurveTimeline.BEZIER_SIZE; + var type = curves[i]; + if (type == CurveTimeline.LINEAR) + return percent; + if (type == CurveTimeline.STEPPED) + return 0; + i++; + var x = 0; + for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) { + x = curves[i]; + if (x >= percent) { + var prevX = void 0, prevY = void 0; + if (i == start) { + prevX = 0; + prevY = 0; + } + else { + prevX = curves[i - 2]; + prevY = curves[i - 1]; + } + return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + var y = curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); + }; + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; + return CurveTimeline; + }()); + spine.CurveTimeline = CurveTimeline; + var RotateTimeline = (function (_super) { + __extends(RotateTimeline, _super); + function RotateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount << 1); + return _this; + } + RotateTimeline.prototype.getPropertyId = function () { + return (TimelineType.rotate << 24) + this.boneIndex; + }; + RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) { + frameIndex <<= 1; + this.frames[frameIndex] = time; + this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; + }; + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation; + return; + case MixBlend.first: + var r_1 = bone.data.rotation - bone.rotation; + bone.rotation += (r_1 - (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360) * alpha; + } + return; + } + if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { + var r_2 = frames[frames.length + RotateTimeline.PREV_ROTATION]; + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation + r_2 * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + r_2 += bone.data.rotation - bone.rotation; + r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360; + case MixBlend.add: + bone.rotation += r_2 * alpha; + } + return; + } + var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES); + var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); + var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; + r = prevRotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * percent; + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + r += bone.data.rotation - bone.rotation; + case MixBlend.add: + bone.rotation += (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha; + } + }; + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; + return RotateTimeline; + }(CurveTimeline)); + spine.RotateTimeline = RotateTimeline; + var TranslateTimeline = (function (_super) { + __extends(TranslateTimeline, _super); + function TranslateTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + return _this; + } + TranslateTimeline.prototype.getPropertyId = function () { + return (TimelineType.translate << 24) + this.boneIndex; + }; + TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) { + frameIndex *= TranslateTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TranslateTimeline.X] = x; + this.frames[frameIndex + TranslateTimeline.Y] = y; + }; + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixBlend.first: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) { + x = frames[frames.length + TranslateTimeline.PREV_X]; + y = frames[frames.length + TranslateTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES); + x = frames[frame + TranslateTimeline.PREV_X]; + y = frames[frame + TranslateTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime)); + x += (frames[frame + TranslateTimeline.X] - x) * percent; + y += (frames[frame + TranslateTimeline.Y] - y) * percent; + } + switch (blend) { + case MixBlend.setup: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case MixBlend.add: + bone.x += x * alpha; + bone.y += y * alpha; + } + }; + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; + return TranslateTimeline; + }(CurveTimeline)); + spine.TranslateTimeline = TranslateTimeline; + var ScaleTimeline = (function (_super) { + __extends(ScaleTimeline, _super); + function ScaleTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ScaleTimeline.prototype.getPropertyId = function () { + return (TimelineType.scale << 24) + this.boneIndex; + }; + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixBlend.first: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) { + x = frames[frames.length + ScaleTimeline.PREV_X] * bone.data.scaleX; + y = frames[frames.length + ScaleTimeline.PREV_Y] * bone.data.scaleY; + } + else { + var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES); + x = frames[frame + ScaleTimeline.PREV_X]; + y = frames[frame + ScaleTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime)); + x = (x + (frames[frame + ScaleTimeline.X] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY; + } + if (alpha == 1) { + if (blend == MixBlend.add) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } + else { + bone.scaleX = x; + bone.scaleY = y; + } + } + else { + var bx = 0, by = 0; + if (direction == MixDirection.mixOut) { + switch (blend) { + case MixBlend.setup: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - by) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - by) * alpha; + break; + case MixBlend.add: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * spine.MathUtils.signum(bx) - bone.data.scaleX) * alpha; + bone.scaleY = by + (Math.abs(y) * spine.MathUtils.signum(by) - bone.data.scaleY) * alpha; + } + } + else { + switch (blend) { + case MixBlend.setup: + bx = Math.abs(bone.data.scaleX) * spine.MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * spine.MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bx = Math.abs(bone.scaleX) * spine.MathUtils.signum(x); + by = Math.abs(bone.scaleY) * spine.MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case MixBlend.add: + bx = spine.MathUtils.signum(x); + by = spine.MathUtils.signum(y); + bone.scaleX = Math.abs(bone.scaleX) * bx + (x - Math.abs(bone.data.scaleX) * bx) * alpha; + bone.scaleY = Math.abs(bone.scaleY) * by + (y - Math.abs(bone.data.scaleY) * by) * alpha; + } + } + } + }; + return ScaleTimeline; + }(TranslateTimeline)); + spine.ScaleTimeline = ScaleTimeline; + var ShearTimeline = (function (_super) { + __extends(ShearTimeline, _super); + function ShearTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + ShearTimeline.prototype.getPropertyId = function () { + return (TimelineType.shear << 24) + this.boneIndex; + }; + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var frames = this.frames; + var bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixBlend.first: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + var x = 0, y = 0; + if (time >= frames[frames.length - ShearTimeline.ENTRIES]) { + x = frames[frames.length + ShearTimeline.PREV_X]; + y = frames[frames.length + ShearTimeline.PREV_Y]; + } + else { + var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES); + x = frames[frame + ShearTimeline.PREV_X]; + y = frames[frame + ShearTimeline.PREV_Y]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime)); + x = x + (frames[frame + ShearTimeline.X] - x) * percent; + y = y + (frames[frame + ShearTimeline.Y] - y) * percent; + } + switch (blend) { + case MixBlend.setup: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case MixBlend.first: + case MixBlend.replace: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case MixBlend.add: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + }; + return ShearTimeline; + }(TranslateTimeline)); + spine.ShearTimeline = ShearTimeline; + var ColorTimeline = (function (_super) { + __extends(ColorTimeline, _super); + function ColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + return _this; + } + ColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.color << 24) + this.slotIndex; + }; + ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) { + frameIndex *= ColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + ColorTimeline.R] = r; + this.frames[frameIndex + ColorTimeline.G] = g; + this.frames[frameIndex + ColorTimeline.B] = b; + this.frames[frameIndex + ColorTimeline.A] = a; + }; + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + var frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + slot.color.setFromColor(slot.data.color); + return; + case MixBlend.first: + var color = slot.color, setup = slot.data.color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } + return; + } + var r = 0, g = 0, b = 0, a = 0; + if (time >= frames[frames.length - ColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + ColorTimeline.PREV_R]; + g = frames[i + ColorTimeline.PREV_G]; + b = frames[i + ColorTimeline.PREV_B]; + a = frames[i + ColorTimeline.PREV_A]; + } + else { + var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES); + r = frames[frame + ColorTimeline.PREV_R]; + g = frames[frame + ColorTimeline.PREV_G]; + b = frames[frame + ColorTimeline.PREV_B]; + a = frames[frame + ColorTimeline.PREV_A]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + ColorTimeline.R] - r) * percent; + g += (frames[frame + ColorTimeline.G] - g) * percent; + b += (frames[frame + ColorTimeline.B] - b) * percent; + a += (frames[frame + ColorTimeline.A] - a) * percent; + } + if (alpha == 1) + slot.color.set(r, g, b, a); + else { + var color = slot.color; + if (blend == MixBlend.setup) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + }; + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; + return ColorTimeline; + }(CurveTimeline)); + spine.ColorTimeline = ColorTimeline; + var TwoColorTimeline = (function (_super) { + __extends(TwoColorTimeline, _super); + function TwoColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES); + return _this; + } + TwoColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.twoColor << 24) + this.slotIndex; + }; + TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + }; + TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + var frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + return; + case MixBlend.first: + var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0); + } + return; + } + var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + TwoColorTimeline.PREV_R]; + g = frames[i + TwoColorTimeline.PREV_G]; + b = frames[i + TwoColorTimeline.PREV_B]; + a = frames[i + TwoColorTimeline.PREV_A]; + r2 = frames[i + TwoColorTimeline.PREV_R2]; + g2 = frames[i + TwoColorTimeline.PREV_G2]; + b2 = frames[i + TwoColorTimeline.PREV_B2]; + } + else { + var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES); + r = frames[frame + TwoColorTimeline.PREV_R]; + g = frames[frame + TwoColorTimeline.PREV_G]; + b = frames[frame + TwoColorTimeline.PREV_B]; + a = frames[frame + TwoColorTimeline.PREV_A]; + r2 = frames[frame + TwoColorTimeline.PREV_R2]; + g2 = frames[frame + TwoColorTimeline.PREV_G2]; + b2 = frames[frame + TwoColorTimeline.PREV_B2]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + TwoColorTimeline.R] - r) * percent; + g += (frames[frame + TwoColorTimeline.G] - g) * percent; + b += (frames[frame + TwoColorTimeline.B] - b) * percent; + a += (frames[frame + TwoColorTimeline.A] - a) * percent; + r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent; + g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent; + b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent; + } + if (alpha == 1) { + slot.color.set(r, g, b, a); + slot.darkColor.set(r2, g2, b2, 1); + } + else { + var light = slot.color, dark = slot.darkColor; + if (blend == MixBlend.setup) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + }; + TwoColorTimeline.ENTRIES = 8; + TwoColorTimeline.PREV_TIME = -8; + TwoColorTimeline.PREV_R = -7; + TwoColorTimeline.PREV_G = -6; + TwoColorTimeline.PREV_B = -5; + TwoColorTimeline.PREV_A = -4; + TwoColorTimeline.PREV_R2 = -3; + TwoColorTimeline.PREV_G2 = -2; + TwoColorTimeline.PREV_B2 = -1; + TwoColorTimeline.R = 1; + TwoColorTimeline.G = 2; + TwoColorTimeline.B = 3; + TwoColorTimeline.A = 4; + TwoColorTimeline.R2 = 5; + TwoColorTimeline.G2 = 6; + TwoColorTimeline.B2 = 7; + return TwoColorTimeline; + }(CurveTimeline)); + spine.TwoColorTimeline = TwoColorTimeline; + var AttachmentTimeline = (function () { + function AttachmentTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.attachmentNames = new Array(frameCount); + } + AttachmentTimeline.prototype.getPropertyId = function () { + return (TimelineType.attachment << 24) + this.slotIndex; + }; + AttachmentTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }; + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + if (direction == MixDirection.mixOut) { + if (blend == MixBlend.setup) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (blend == MixBlend.setup || blend == MixBlend.first) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + var frameIndex = 0; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = Animation.binarySearch(frames, time, 1) - 1; + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex] + .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + AttachmentTimeline.prototype.setAttachment = function (skeleton, slot, attachmentName) { + slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + }; + return AttachmentTimeline; + }()); + spine.AttachmentTimeline = AttachmentTimeline; + var zeros = null; + var DeformTimeline = (function (_super) { + __extends(DeformTimeline, _super); + function DeformTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount); + _this.frameVertices = new Array(frameCount); + if (zeros == null) + zeros = spine.Utils.newFloatArray(64); + return _this; + } + DeformTimeline.prototype.getPropertyId = function () { + return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex; + }; + DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { + this.frames[frameIndex] = time; + this.frameVertices[frameIndex] = vertices; + }; + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + var slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof spine.VertexAttachment) || !(slotAttachment.deformAttachment == this.attachment)) + return; + var deformArray = slot.deform; + if (deformArray.length == 0) + blend = MixBlend.setup; + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + var frames = this.frames; + if (time < frames[0]) { + var vertexAttachment = slotAttachment; + switch (blend) { + case MixBlend.setup: + deformArray.length = 0; + return; + case MixBlend.first: + if (alpha == 1) { + deformArray.length = 0; + break; + } + var deform_1 = spine.Utils.setArraySize(deformArray, vertexCount); + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform_1[i] += (setupVertices[i] - deform_1[i]) * alpha; + } + else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform_1[i] *= alpha; + } + } + return; + } + var deform = spine.Utils.setArraySize(deformArray, vertexCount); + if (time >= frames[frames.length - 1]) { + var lastVertices = frameVertices[frames.length - 1]; + if (alpha == 1) { + if (blend == MixBlend.add) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_1 = 0; i_1 < vertexCount; i_1++) { + deform[i_1] += lastVertices[i_1] - setupVertices[i_1]; + } + } + else { + for (var i_2 = 0; i_2 < vertexCount; i_2++) + deform[i_2] += lastVertices[i_2]; + } + } + else { + spine.Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } + } + else { + switch (blend) { + case MixBlend.setup: { + var vertexAttachment_1 = slotAttachment; + if (vertexAttachment_1.bones == null) { + var setupVertices = vertexAttachment_1.vertices; + for (var i_3 = 0; i_3 < vertexCount; i_3++) { + var setup = setupVertices[i_3]; + deform[i_3] = setup + (lastVertices[i_3] - setup) * alpha; + } + } + else { + for (var i_4 = 0; i_4 < vertexCount; i_4++) + deform[i_4] = lastVertices[i_4] * alpha; + } + break; + } + case MixBlend.first: + case MixBlend.replace: + for (var i_5 = 0; i_5 < vertexCount; i_5++) + deform[i_5] += (lastVertices[i_5] - deform[i_5]) * alpha; + break; + case MixBlend.add: + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_6 = 0; i_6 < vertexCount; i_6++) { + deform[i_6] += (lastVertices[i_6] - setupVertices[i_6]) * alpha; + } + } + else { + for (var i_7 = 0; i_7 < vertexCount; i_7++) + deform[i_7] += lastVertices[i_7] * alpha; + } + } + } + return; + } + var frame = Animation.binarySearch(frames, time); + var prevVertices = frameVertices[frame - 1]; + var nextVertices = frameVertices[frame]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + if (alpha == 1) { + if (blend == MixBlend.add) { + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_8 = 0; i_8 < vertexCount; i_8++) { + var prev = prevVertices[i_8]; + deform[i_8] += prev + (nextVertices[i_8] - prev) * percent - setupVertices[i_8]; + } + } + else { + for (var i_9 = 0; i_9 < vertexCount; i_9++) { + var prev = prevVertices[i_9]; + deform[i_9] += prev + (nextVertices[i_9] - prev) * percent; + } + } + } + else { + for (var i_10 = 0; i_10 < vertexCount; i_10++) { + var prev = prevVertices[i_10]; + deform[i_10] = prev + (nextVertices[i_10] - prev) * percent; + } + } + } + else { + switch (blend) { + case MixBlend.setup: { + var vertexAttachment_2 = slotAttachment; + if (vertexAttachment_2.bones == null) { + var setupVertices = vertexAttachment_2.vertices; + for (var i_11 = 0; i_11 < vertexCount; i_11++) { + var prev = prevVertices[i_11], setup = setupVertices[i_11]; + deform[i_11] = setup + (prev + (nextVertices[i_11] - prev) * percent - setup) * alpha; + } + } + else { + for (var i_12 = 0; i_12 < vertexCount; i_12++) { + var prev = prevVertices[i_12]; + deform[i_12] = (prev + (nextVertices[i_12] - prev) * percent) * alpha; + } + } + break; + } + case MixBlend.first: + case MixBlend.replace: + for (var i_13 = 0; i_13 < vertexCount; i_13++) { + var prev = prevVertices[i_13]; + deform[i_13] += (prev + (nextVertices[i_13] - prev) * percent - deform[i_13]) * alpha; + } + break; + case MixBlend.add: + var vertexAttachment = slotAttachment; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i_14 = 0; i_14 < vertexCount; i_14++) { + var prev = prevVertices[i_14]; + deform[i_14] += (prev + (nextVertices[i_14] - prev) * percent - setupVertices[i_14]) * alpha; + } + } + else { + for (var i_15 = 0; i_15 < vertexCount; i_15++) { + var prev = prevVertices[i_15]; + deform[i_15] += (prev + (nextVertices[i_15] - prev) * percent) * alpha; + } + } + } + } + }; + return DeformTimeline; + }(CurveTimeline)); + spine.DeformTimeline = DeformTimeline; + var EventTimeline = (function () { + function EventTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.events = new Array(frameCount); + } + EventTimeline.prototype.getPropertyId = function () { + return TimelineType.event << 24; + }; + EventTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + EventTimeline.prototype.setFrame = function (frameIndex, event) { + this.frames[frameIndex] = event.time; + this.events[frameIndex] = event; + }; + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (firedEvents == null) + return; + var frames = this.frames; + var frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } + else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + var frame = 0; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.binarySearch(frames, lastTime); + var frameTime = frames[frame]; + while (frame > 0) { + if (frames[frame - 1] != frameTime) + break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.push(this.events[frame]); + }; + return EventTimeline; + }()); + spine.EventTimeline = EventTimeline; + var DrawOrderTimeline = (function () { + function DrawOrderTimeline(frameCount) { + this.frames = spine.Utils.newFloatArray(frameCount); + this.drawOrders = new Array(frameCount); + } + DrawOrderTimeline.prototype.getPropertyId = function () { + return TimelineType.drawOrder << 24; + }; + DrawOrderTimeline.prototype.getFrameCount = function () { + return this.frames.length; + }; + DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) { + this.frames[frameIndex] = time; + this.drawOrders[frameIndex] = drawOrder; + }; + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var drawOrder = skeleton.drawOrder; + var slots = skeleton.slots; + if (direction == MixDirection.mixOut) { + if (blend == MixBlend.setup) + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frames = this.frames; + if (time < frames[0]) { + if (blend == MixBlend.setup || blend == MixBlend.first) + spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + var frame = 0; + if (time >= frames[frames.length - 1]) + frame = frames.length - 1; + else + frame = Animation.binarySearch(frames, time) - 1; + var drawOrderToSetupIndex = this.drawOrders[frame]; + if (drawOrderToSetupIndex == null) + spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length); + else { + for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + }; + return DrawOrderTimeline; + }()); + spine.DrawOrderTimeline = DrawOrderTimeline; + var IkConstraintTimeline = (function (_super) { + __extends(IkConstraintTimeline, _super); + function IkConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + return _this; + } + IkConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; + }; + IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, softness, bendDirection, compress, stretch) { + frameIndex *= IkConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; + this.frames[frameIndex + IkConstraintTimeline.SOFTNESS] = softness; + this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; + this.frames[frameIndex + IkConstraintTimeline.COMPRESS] = compress ? 1 : 0; + this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0; + }; + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (!constraint.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case MixBlend.first: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { + if (blend == MixBlend.setup) { + constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + + (frames[frames.length + IkConstraintTimeline.PREV_SOFTNESS] - constraint.data.softness) * alpha; + if (direction == MixDirection.mixOut) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + else { + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frames.length + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frames.length + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + else { + constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; + constraint.softness += (frames[frames.length + IkConstraintTimeline.PREV_SOFTNESS] - constraint.softness) * alpha; + if (direction == MixDirection.mixIn) { + constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frames.length + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frames.length + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + return; + } + var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES); + var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; + var softness = frames[frame + IkConstraintTimeline.PREV_SOFTNESS]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); + if (blend == MixBlend.setup) { + constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + + (softness + (frames[frame + IkConstraintTimeline.SOFTNESS] - softness) * percent - constraint.data.softness) * alpha; + if (direction == MixDirection.mixOut) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + else { + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frame + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frame + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + else { + constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; + constraint.softness += (softness + (frames[frame + IkConstraintTimeline.SOFTNESS] - softness) * percent - constraint.softness) * alpha; + if (direction == MixDirection.mixIn) { + constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.compress = frames[frame + IkConstraintTimeline.PREV_COMPRESS] != 0; + constraint.stretch = frames[frame + IkConstraintTimeline.PREV_STRETCH] != 0; + } + } + }; + IkConstraintTimeline.ENTRIES = 6; + IkConstraintTimeline.PREV_TIME = -6; + IkConstraintTimeline.PREV_MIX = -5; + IkConstraintTimeline.PREV_SOFTNESS = -4; + IkConstraintTimeline.PREV_BEND_DIRECTION = -3; + IkConstraintTimeline.PREV_COMPRESS = -2; + IkConstraintTimeline.PREV_STRETCH = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.SOFTNESS = 2; + IkConstraintTimeline.BEND_DIRECTION = 3; + IkConstraintTimeline.COMPRESS = 4; + IkConstraintTimeline.STRETCH = 5; + return IkConstraintTimeline; + }(CurveTimeline)); + spine.IkConstraintTimeline = IkConstraintTimeline; + var TransformConstraintTimeline = (function (_super) { + __extends(TransformConstraintTimeline, _super); + function TransformConstraintTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + return _this; + } + TransformConstraintTimeline.prototype.getPropertyId = function () { + return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; + }; + TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) { + frameIndex *= TransformConstraintTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix; + this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; + this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; + }; + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (!constraint.active) + return; + if (time < frames[0]) { + var data = constraint.data; + switch (blend) { + case MixBlend.setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixBlend.first: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; + } + return; + } + var rotate = 0, translate = 0, scale = 0, shear = 0; + if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) { + var i = frames.length; + rotate = frames[i + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[i + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[i + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[i + TransformConstraintTimeline.PREV_SHEAR]; + } + else { + var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES); + rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE]; + translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE]; + scale = frames[frame + TransformConstraintTimeline.PREV_SCALE]; + shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent; + scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; + shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; + } + if (blend == MixBlend.setup) { + var data = constraint.data; + constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; + constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; + constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; + constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + constraint.scaleMix += (scale - constraint.scaleMix) * alpha; + constraint.shearMix += (shear - constraint.shearMix) * alpha; + } + }; + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; + return TransformConstraintTimeline; + }(CurveTimeline)); + spine.TransformConstraintTimeline = TransformConstraintTimeline; + var PathConstraintPositionTimeline = (function (_super) { + __extends(PathConstraintPositionTimeline, _super); + function PathConstraintPositionTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + return _this; + } + PathConstraintPositionTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; + }; + PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) { + frameIndex *= PathConstraintPositionTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; + }; + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.position = constraint.data.position; + return; + case MixBlend.first: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } + return; + } + var position = 0; + if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES]) + position = frames[frames.length + PathConstraintPositionTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES); + position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); + position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; + } + if (blend == MixBlend.setup) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + }; + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; + return PathConstraintPositionTimeline; + }(CurveTimeline)); + spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; + var PathConstraintSpacingTimeline = (function (_super) { + __extends(PathConstraintSpacingTimeline, _super); + function PathConstraintSpacingTimeline(frameCount) { + return _super.call(this, frameCount) || this; + } + PathConstraintSpacingTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; + }; + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.spacing = constraint.data.spacing; + return; + case MixBlend.first: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } + return; + } + var spacing = 0; + if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES]) + spacing = frames[frames.length + PathConstraintSpacingTimeline.PREV_VALUE]; + else { + var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES); + spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); + spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; + } + if (blend == MixBlend.setup) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + }; + return PathConstraintSpacingTimeline; + }(PathConstraintPositionTimeline)); + spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline; + var PathConstraintMixTimeline = (function (_super) { + __extends(PathConstraintMixTimeline, _super); + function PathConstraintMixTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + return _this; + } + PathConstraintMixTimeline.prototype.getPropertyId = function () { + return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; + }; + PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) { + frameIndex *= PathConstraintMixTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; + this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; + }; + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + var frames = this.frames; + var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixBlend.first: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; + } + return; + } + var rotate = 0, translate = 0; + if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) { + rotate = frames[frames.length + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frames.length + PathConstraintMixTimeline.PREV_TRANSLATE]; + } + else { + var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES); + rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE]; + translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime)); + rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; + translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; + } + if (blend == MixBlend.setup) { + constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; + constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; + } + else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + } + }; + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; + return PathConstraintMixTimeline; + }(CurveTimeline)); + spine.PathConstraintMixTimeline = PathConstraintMixTimeline; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationState = (function () { + function AnimationState(data) { + this.tracks = new Array(); + this.timeScale = 1; + this.unkeyedState = 0; + this.events = new Array(); + this.listeners = new Array(); + this.queue = new EventQueue(this); + this.propertyIDs = new spine.IntSet(); + this.animationsChanged = false; + this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); + this.data = data; + } + AnimationState.prototype.update = function (delta) { + delta *= this.timeScale; + var tracks = this.tracks; + for (var i = 0, n = tracks.length; i < n; i++) { + var current = tracks[i]; + if (current == null) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + var currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + var next = current.next; + if (next != null) { + var nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom != null) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } + else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) { + var from = current.mixingFrom; + current.mixingFrom = null; + if (from != null) + from.mixingTo = null; + while (from != null) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + }; + AnimationState.prototype.updateMixingFrom = function (to, delta) { + var from = to.mixingFrom; + if (from == null) + return true; + var finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + }; + AnimationState.prototype.apply = function (skeleton) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + var events = this.events; + var tracks = this.tracks; + var applied = false; + for (var i_16 = 0, n_1 = tracks.length; i_16 < n_1; i_16++) { + var current = tracks[i_16]; + if (current == null || current.delay > 0) + continue; + applied = true; + var blend = i_16 == 0 ? spine.MixBlend.first : current.mixBlend; + var mix = current.alpha; + if (current.mixingFrom != null) + mix *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && current.next == null) + mix = 0; + var animationLast = current.animationLast, animationTime = current.getAnimationTime(); + var timelineCount = current.animation.timelines.length; + var timelines = current.animation.timelines; + if ((i_16 == 0 && mix == 1) || blend == spine.MixBlend.add) { + for (var ii = 0; ii < timelineCount; ii++) { + spine.Utils.webkit602BugfixHelper(mix, blend); + var timeline = timelines[ii]; + if (timeline instanceof spine.AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true); + else + timeline.apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn); + } + } + else { + var timelineMode = current.timelineMode; + var firstFrame = current.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = current.timelinesRotation; + for (var ii = 0; ii < timelineCount; ii++) { + var timeline_1 = timelines[ii]; + var timelineBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup; + if (timeline_1 instanceof spine.RotateTimeline) { + this.applyRotateTimeline(timeline_1, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame); + } + else if (timeline_1 instanceof spine.AttachmentTimeline) { + this.applyAttachmentTimeline(timeline_1, skeleton, animationTime, blend, true); + } + else { + spine.Utils.webkit602BugfixHelper(mix, blend); + timeline_1.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + AnimationState.SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + }; + AnimationState.prototype.applyMixingFrom = function (to, skeleton, blend) { + var from = to.mixingFrom; + if (from.mixingFrom != null) + this.applyMixingFrom(from, skeleton, blend); + var mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == spine.MixBlend.first) + blend = spine.MixBlend.setup; + } + else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != spine.MixBlend.first) + blend = from.mixBlend; + } + var events = mix < from.eventThreshold ? this.events : null; + var attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + var animationLast = from.animationLast, animationTime = from.getAnimationTime(); + var timelineCount = from.animation.timelines.length; + var timelines = from.animation.timelines; + var alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + if (blend == spine.MixBlend.add) { + for (var i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, spine.MixDirection.mixOut); + } + else { + var timelineMode = from.timelineMode; + var timelineHoldMix = from.timelineHoldMix; + var firstFrame = from.timelinesRotation.length == 0; + if (firstFrame) + spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); + var timelinesRotation = from.timelinesRotation; + from.totalAlpha = 0; + for (var i = 0; i < timelineCount; i++) { + var timeline = timelines[i]; + var direction = spine.MixDirection.mixOut; + var timelineBlend = void 0; + var alpha = 0; + switch (timelineMode[i]) { + case AnimationState.SUBSEQUENT: + if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case AnimationState.FIRST: + timelineBlend = spine.MixBlend.setup; + alpha = alphaMix; + break; + case AnimationState.HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case AnimationState.HOLD_FIRST: + timelineBlend = spine.MixBlend.setup; + alpha = alphaHold; + break; + default: + timelineBlend = spine.MixBlend.setup; + var holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof spine.AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments); + else { + spine.Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof spine.DrawOrderTimeline && timelineBlend == spine.MixBlend.setup) + direction = spine.MixDirection.mixIn; + timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + }; + AnimationState.prototype.applyAttachmentTimeline = function (timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) + return; + var frames = timeline.frames; + if (time < frames[0]) { + if (blend == spine.MixBlend.setup || blend == spine.MixBlend.first) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } + else { + var frameIndex; + if (time >= frames[frames.length - 1]) + frameIndex = frames.length - 1; + else + frameIndex = spine.Animation.binarySearch(frames, time) - 1; + this.setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments); + } + if (slot.attachmentState <= this.unkeyedState) + slot.attachmentState = this.unkeyedState + AnimationState.SETUP; + }; + AnimationState.prototype.setAttachment = function (skeleton, slot, attachmentName, attachments) { + slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) + slot.attachmentState = this.unkeyedState + AnimationState.CURRENT; + }; + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, spine.MixDirection.mixIn); + return; + } + var rotateTimeline = timeline; + var frames = rotateTimeline.frames; + var bone = skeleton.bones[rotateTimeline.boneIndex]; + if (!bone.active) + return; + var r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case spine.MixBlend.setup: + bone.rotation = bone.data.rotation; + default: + return; + case spine.MixBlend.first: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } + else { + r1 = blend == spine.MixBlend.setup ? bone.data.rotation : bone.rotation; + if (time >= frames[frames.length - spine.RotateTimeline.ENTRIES]) + r2 = bone.data.rotation + frames[frames.length + spine.RotateTimeline.PREV_ROTATION]; + else { + var frame = spine.Animation.binarySearch(frames, time, spine.RotateTimeline.ENTRIES); + var prevRotation = frames[frame + spine.RotateTimeline.PREV_ROTATION]; + var frameTime = frames[frame]; + var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + spine.RotateTimeline.PREV_TIME] - frameTime)); + r2 = frames[frame + spine.RotateTimeline.ROTATION] - prevRotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + r2 = prevRotation + r2 * percent + bone.data.rotation; + r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; + } + } + var total = 0, diff = r2 - r1; + diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } + else { + var lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } + else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + var current = diff > 0, dir = lastTotal >= 0; + if (spine.MathUtils.signum(lastDiff) != spine.MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * spine.MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * spine.MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360; + }; + AnimationState.prototype.queueEvents = function (entry, animationTime) { + var animationStart = entry.animationStart, animationEnd = entry.animationEnd; + var duration = animationEnd - animationStart; + var trackLastWrapped = entry.trackLast % duration; + var events = this.events; + var i = 0, n = events.length; + for (; i < n; i++) { + var event_1 = events[i]; + if (event_1.time < trackLastWrapped) + break; + if (event_1.time > animationEnd) + continue; + this.queue.event(entry, event_1); + } + var complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + var event_2 = events[i]; + if (event_2.time < animationStart) + continue; + this.queue.event(entry, events[i]); + } + }; + AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.clearTrack = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return; + var current = this.tracks[trackIndex]; + if (current == null) + return; + this.queue.end(current); + this.disposeNext(current); + var entry = current; + while (true) { + var from = entry.mixingFrom; + if (from == null) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + }; + AnimationState.prototype.setCurrent = function (index, current, interrupt) { + var from = this.expandToIndex(index); + this.tracks[index] = current; + if (from != null) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom != null && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + }; + AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + }; + AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) { + if (animation == null) + throw new Error("animation cannot be null."); + var interrupt = true; + var current = this.expandToIndex(trackIndex); + if (current != null) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.disposeNext(current); + current = current.mixingFrom; + interrupt = false; + } + else + this.disposeNext(current); + } + var entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + }; + AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (animation == null) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + }; + AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) { + if (animation == null) + throw new Error("animation cannot be null."); + var last = this.expandToIndex(trackIndex); + if (last != null) { + while (last.next != null) + last = last.next; + } + var entry = this.trackEntry(trackIndex, animation, loop, last); + if (last == null) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } + else { + last.next = entry; + if (delay <= 0) { + var duration = last.animationEnd - last.animationStart; + if (duration != 0) { + if (last.loop) + delay += duration * (1 + ((last.trackTime / duration) | 0)); + else + delay += Math.max(duration, last.trackTime); + delay -= this.data.getMix(last.animation, animation); + } + else + delay = last.trackTime; + } + } + entry.delay = delay; + return entry; + }; + AnimationState.prototype.setEmptyAnimation = function (trackIndex, mixDuration) { + var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.addEmptyAnimation = function (trackIndex, mixDuration, delay) { + if (delay <= 0) + delay -= mixDuration; + var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + }; + AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (var i = 0, n = this.tracks.length; i < n; i++) { + var current = this.tracks[i]; + if (current != null) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + }; + AnimationState.prototype.expandToIndex = function (index) { + if (index < this.tracks.length) + return this.tracks[index]; + spine.Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + }; + AnimationState.prototype.trackEntry = function (trackIndex, animation, loop, last) { + var entry = this.trackEntryPool.obtain(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.interruptAlpha = 1; + entry.mixTime = 0; + entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); + entry.mixBlend = spine.MixBlend.replace; + return entry; + }; + AnimationState.prototype.disposeNext = function (entry) { + var next = entry.next; + while (next != null) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + }; + AnimationState.prototype._animationsChanged = function () { + this.animationsChanged = false; + this.propertyIDs.clear(); + for (var i = 0, n = this.tracks.length; i < n; i++) { + var entry = this.tracks[i]; + if (entry == null) + continue; + while (entry.mixingFrom != null) + entry = entry.mixingFrom; + do { + if (entry.mixingFrom == null || entry.mixBlend != spine.MixBlend.add) + this.computeHold(entry); + entry = entry.mixingTo; + } while (entry != null); + } + }; + AnimationState.prototype.computeHold = function (entry) { + var to = entry.mixingTo; + var timelines = entry.animation.timelines; + var timelinesCount = entry.animation.timelines.length; + var timelineMode = spine.Utils.setArraySize(entry.timelineMode, timelinesCount); + entry.timelineHoldMix.length = 0; + var timelineDipMix = spine.Utils.setArraySize(entry.timelineHoldMix, timelinesCount); + var propertyIDs = this.propertyIDs; + if (to != null && to.holdPrevious) { + for (var i = 0; i < timelinesCount; i++) { + timelineMode[i] = propertyIDs.add(timelines[i].getPropertyId()) ? AnimationState.HOLD_FIRST : AnimationState.HOLD_SUBSEQUENT; + } + return; + } + outer: for (var i = 0; i < timelinesCount; i++) { + var timeline = timelines[i]; + var id = timeline.getPropertyId(); + if (!propertyIDs.add(id)) + timelineMode[i] = AnimationState.SUBSEQUENT; + else if (to == null || timeline instanceof spine.AttachmentTimeline || timeline instanceof spine.DrawOrderTimeline + || timeline instanceof spine.EventTimeline || !to.animation.hasTimeline(id)) { + timelineMode[i] = AnimationState.FIRST; + } + else { + for (var next = to.mixingTo; next != null; next = next.mixingTo) { + if (next.animation.hasTimeline(id)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = AnimationState.HOLD_MIX; + timelineDipMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = AnimationState.HOLD_FIRST; + } + } + }; + AnimationState.prototype.getCurrent = function (trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + }; + AnimationState.prototype.addListener = function (listener) { + if (listener == null) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + }; + AnimationState.prototype.removeListener = function (listener) { + var index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + }; + AnimationState.prototype.clearListeners = function () { + this.listeners.length = 0; + }; + AnimationState.prototype.clearListenerNotifications = function () { + this.queue.clear(); + }; + AnimationState.emptyAnimation = new spine.Animation("", [], 0); + AnimationState.SUBSEQUENT = 0; + AnimationState.FIRST = 1; + AnimationState.HOLD_SUBSEQUENT = 2; + AnimationState.HOLD_FIRST = 3; + AnimationState.HOLD_MIX = 4; + AnimationState.SETUP = 1; + AnimationState.CURRENT = 2; + return AnimationState; + }()); + spine.AnimationState = AnimationState; + var TrackEntry = (function () { + function TrackEntry() { + this.mixBlend = spine.MixBlend.replace; + this.timelineMode = new Array(); + this.timelineHoldMix = new Array(); + this.timelinesRotation = new Array(); + } + TrackEntry.prototype.reset = function () { + this.next = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + }; + TrackEntry.prototype.getAnimationTime = function () { + if (this.loop) { + var duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return (this.trackTime % duration) + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + }; + TrackEntry.prototype.setAnimationLast = function (animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + }; + TrackEntry.prototype.isComplete = function () { + return this.trackTime >= this.animationEnd - this.animationStart; + }; + TrackEntry.prototype.resetRotationDirections = function () { + this.timelinesRotation.length = 0; + }; + return TrackEntry; + }()); + spine.TrackEntry = TrackEntry; + var EventQueue = (function () { + function EventQueue(animState) { + this.objects = []; + this.drainDisabled = false; + this.animState = animState; + } + EventQueue.prototype.start = function (entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.interrupt = function (entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + }; + EventQueue.prototype.end = function (entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + }; + EventQueue.prototype.dispose = function (entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + }; + EventQueue.prototype.complete = function (entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + }; + EventQueue.prototype.event = function (entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + }; + EventQueue.prototype.drain = function () { + if (this.drainDisabled) + return; + this.drainDisabled = true; + var objects = this.objects; + var listeners = this.animState.listeners; + for (var i = 0; i < objects.length; i += 2) { + var type = objects[i]; + var entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener != null && entry.listener.start) + entry.listener.start(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].start) + listeners[ii].start(entry); + break; + case EventType.interrupt: + if (entry.listener != null && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].interrupt) + listeners[ii].interrupt(entry); + break; + case EventType.end: + if (entry.listener != null && entry.listener.end) + entry.listener.end(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].end) + listeners[ii].end(entry); + case EventType.dispose: + if (entry.listener != null && entry.listener.dispose) + entry.listener.dispose(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].dispose) + listeners[ii].dispose(entry); + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener != null && entry.listener.complete) + entry.listener.complete(entry); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].complete) + listeners[ii].complete(entry); + break; + case EventType.event: + var event_3 = objects[i++ + 2]; + if (entry.listener != null && entry.listener.event) + entry.listener.event(entry, event_3); + for (var ii = 0; ii < listeners.length; ii++) + if (listeners[ii].event) + listeners[ii].event(entry, event_3); + break; + } + } + this.clear(); + this.drainDisabled = false; + }; + EventQueue.prototype.clear = function () { + this.objects.length = 0; + }; + return EventQueue; + }()); + spine.EventQueue = EventQueue; + var EventType; + (function (EventType) { + EventType[EventType["start"] = 0] = "start"; + EventType[EventType["interrupt"] = 1] = "interrupt"; + EventType[EventType["end"] = 2] = "end"; + EventType[EventType["dispose"] = 3] = "dispose"; + EventType[EventType["complete"] = 4] = "complete"; + EventType[EventType["event"] = 5] = "event"; + })(EventType = spine.EventType || (spine.EventType = {})); + var AnimationStateAdapter = (function () { + function AnimationStateAdapter() { + } + AnimationStateAdapter.prototype.start = function (entry) { + }; + AnimationStateAdapter.prototype.interrupt = function (entry) { + }; + AnimationStateAdapter.prototype.end = function (entry) { + }; + AnimationStateAdapter.prototype.dispose = function (entry) { + }; + AnimationStateAdapter.prototype.complete = function (entry) { + }; + AnimationStateAdapter.prototype.event = function (entry, event) { + }; + return AnimationStateAdapter; + }()); + spine.AnimationStateAdapter = AnimationStateAdapter; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AnimationStateData = (function () { + function AnimationStateData(skeletonData) { + this.animationToMixTime = {}; + this.defaultMix = 0; + if (skeletonData == null) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + AnimationStateData.prototype.setMix = function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (from == null) + throw new Error("Animation not found: " + fromName); + var to = this.skeletonData.findAnimation(toName); + if (to == null) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + }; + AnimationStateData.prototype.setMixWith = function (from, to, duration) { + if (from == null) + throw new Error("from cannot be null."); + if (to == null) + throw new Error("to cannot be null."); + var key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + }; + AnimationStateData.prototype.getMix = function (from, to) { + var key = from.name + "." + to.name; + var value = this.animationToMixTime[key]; + return value === undefined ? this.defaultMix : value; + }; + return AnimationStateData; + }()); + spine.AnimationStateData = AnimationStateData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AssetManager = (function () { + function AssetManager(textureLoader, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.rawDataUris = {}; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + } + AssetManager.prototype.downloadText = function (url, success, error) { + var request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + if (this.rawDataUris[url]) + url = this.rawDataUris[url]; + request.open("GET", url, true); + request.onload = function () { + if (request.status == 200) { + success(request.responseText); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.prototype.downloadBinary = function (url, success, error) { + var request = new XMLHttpRequest(); + if (this.rawDataUris[url]) + url = this.rawDataUris[url]; + request.open("GET", url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status == 200) { + success(new Uint8Array(request.response)); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.prototype.setRawDataURI = function (path, data) { + this.rawDataUris[this.pathPrefix + path] = data; + }; + AssetManager.prototype.loadBinary = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + this.downloadBinary(path, function (data) { + _this.assets[path] = data; + if (success) + success(path, data); + _this.toLoad--; + _this.loaded++; + }, function (state, responseText) { + _this.errors[path] = "Couldn't load binary " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load binary " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.loadText = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + this.downloadText(path, function (data) { + _this.assets[path] = data; + if (success) + success(path, data); + _this.toLoad--; + _this.loaded++; + }, function (state, responseText) { + _this.errors[path] = "Couldn't load text " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load text " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.loadTexture = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + var storagePath = path; + this.toLoad++; + var img = new Image(); + img.crossOrigin = "anonymous"; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[storagePath] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; + if (this.rawDataUris[path]) + path = this.rawDataUris[path]; + img.src = path; + }; + AssetManager.prototype.loadTextureAtlas = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : ""; + path = this.pathPrefix + path; + this.toLoad++; + this.downloadText(path, function (atlasData) { + var pagesLoaded = { count: 0 }; + var atlasPages = new Array(); + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + atlasPages.push(parent == "" ? path : parent + "/" + path); + var image = document.createElement("img"); + image.width = 16; + image.height = 16; + return new spine.FakeTexture(image); + }); + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + return; + } + var _loop_1 = function (atlasPage) { + var pageLoadError = false; + _this.loadTexture(atlasPage, function (imagePath, image) { + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + if (!pageLoadError) { + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + return _this.get(parent == "" ? path : parent + "/" + path); + }); + _this.assets[path] = atlas; + if (success) + success(path, atlas); + _this.toLoad--; + _this.loaded++; + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + } + } + else { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + } + }, function (imagePath, errorMessage) { + pageLoadError = true; + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + }); + }; + for (var _i = 0, atlasPages_1 = atlasPages; _i < atlasPages_1.length; _i++) { + var atlasPage = atlasPages_1[_i]; + _loop_1(atlasPage); + } + }, function (state, responseText) { + _this.errors[path] = "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); + }; + AssetManager.prototype.get = function (path) { + path = this.pathPrefix + path; + return this.assets[path]; + }; + AssetManager.prototype.remove = function (path) { + path = this.pathPrefix + path; + var asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + this.assets[path] = null; + }; + AssetManager.prototype.removeAll = function () { + for (var key in this.assets) { + var asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + }; + AssetManager.prototype.isLoadingComplete = function () { + return this.toLoad == 0; + }; + AssetManager.prototype.getToLoad = function () { + return this.toLoad; + }; + AssetManager.prototype.getLoaded = function () { + return this.loaded; + }; + AssetManager.prototype.dispose = function () { + this.removeAll(); + }; + AssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + AssetManager.prototype.getErrors = function () { + return this.errors; + }; + return AssetManager; + }()); + spine.AssetManager = AssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AtlasAttachmentLoader = (function () { + function AtlasAttachmentLoader(atlas) { + this.atlas = atlas; + } + AtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.RegionAttachment(name); + attachment.setRegion(region); + return attachment; + }; + AtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) { + var region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + var attachment = new spine.MeshAttachment(name); + attachment.region = region; + return attachment; + }; + AtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) { + return new spine.BoundingBoxAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { + return new spine.PathAttachment(name); + }; + AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { + return new spine.PointAttachment(name); + }; + AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) { + return new spine.ClippingAttachment(name); + }; + return AtlasAttachmentLoader; + }()); + spine.AtlasAttachmentLoader = AtlasAttachmentLoader; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BlendMode; + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(BlendMode = spine.BlendMode || (spine.BlendMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.worldX = 0; + this.sorted = false; + this.active = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + Bone.prototype.isActive = function () { + return this.active; + }; + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var skeleton = this.skeleton; + var rotationY = rotation + 90 + shearY; + var sx = skeleton.scaleX; + var sy = skeleton.scaleY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX * sx; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY * sx; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX * sy; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case spine.TransformMode.Normal: { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case spine.TransformMode.OnlyTranslation: { + var rotationY = rotation + 90 + shearY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case spine.TransformMode.NoRotationOrReflection: { + var s = pa * pa + pc * pc; + var prx = 0; + if (s > 0.0001) { + s = Math.abs(pa * pd - pb * pc) / s; + pa /= this.skeleton.scaleX; + pc /= this.skeleton.scaleY; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; + } + else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; + } + var rx = rotation + shearX - prx; + var ry = rotation + shearY - prx + 90; + var la = spine.MathUtils.cosDeg(rx) * scaleX; + var lb = spine.MathUtils.cosDeg(ry) * scaleY; + var lc = spine.MathUtils.sinDeg(rx) * scaleX; + var ld = spine.MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: { + var cos = spine.MathUtils.cosDeg(rotation); + var sin = spine.MathUtils.sinDeg(rotation); + var za = (pa * cos + pb * sin) / this.skeleton.scaleX; + var zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + var s = Math.sqrt(za * za + zc * zc); + if (s > 0.00001) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.data.transformMode == spine.TransformMode.NoScale + && (pa * pd - pb * pc < 0) != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + var r = Math.PI / 2 + Math.atan2(zc, za); + var zb = Math.cos(r) * s; + var zd = Math.sin(r) * s; + var la = spine.MathUtils.cosDeg(shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; + var lc = spine.MathUtils.sinDeg(shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + }; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + }; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.c * this.c); + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.b * this.b + this.d * this.d); + }; + Bone.prototype.updateAppliedTransform = function () { + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + this.ax = this.worldX; + this.ay = this.worldY; + this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + return; + } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = (dx * pd * pid - dy * pb * pid); + this.ay = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + } + else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; + } + }; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; + }; + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + }; + Bone.prototype.worldToLocalRotation = function (worldRotation) { + var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg + this.rotation - this.shearX; + }; + Bone.prototype.localToWorldRotation = function (localRotation) { + localRotation -= this.rotation - this.shearX; + var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; + return Bone; + }()); + spine.Bone = Bone; +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoneData = (function () { + function BoneData(index, name, parent) { + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + this.skinRequired = false; + this.color = new spine.Color(); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + return BoneData; + }()); + spine.BoneData = BoneData; + var TransformMode; + (function (TransformMode) { + TransformMode[TransformMode["Normal"] = 0] = "Normal"; + TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; + TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(TransformMode = spine.TransformMode || (spine.TransformMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var ConstraintData = (function () { + function ConstraintData(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } + return ConstraintData; + }()); + spine.ConstraintData = ConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; +})(spine || (spine = {})); +var spine; +(function (spine) { + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.bendDirection = 0; + this.compress = false; + this.stretch = false; + this.mix = 1; + this.softness = 0; + this.active = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + IkConstraint.prototype.isActive = function () { + return this.active; + }; + IkConstraint.prototype.apply = function () { + this.update(); + }; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.softness, this.mix); + break; + } + }; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, compress, stretch, uniform, alpha) { + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var p = bone.parent; + var pa = p.a, pb = p.b, pc = p.c, pd = p.d; + var rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.data.transformMode) { + case spine.TransformMode.OnlyTranslation: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + break; + case spine.TransformMode.NoRotationOrReflection: + var s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + var sa = pa / bone.skeleton.scaleX; + var sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * spine.MathUtils.radDeg; + default: + var x = targetX - p.worldX, y = targetY - p.worldY; + var d = pa * pd - pb * pc; + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + rotationIK += Math.atan2(ty, tx) * spine.MathUtils.radDeg; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + var sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.data.transformMode) { + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); + if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) { + var s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); + }; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, stretch, softness, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); + return; + } + if (!parent.appliedValid) + parent.updateAppliedTransform(); + if (!child.appliedValid) + child.updateAppliedTransform(); + var px = parent.ax, py = parent.ay, psx = parent.ascaleX, sx = psx, psy = parent.ascaleY, csx = child.ascaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } + else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } + else + os2 = 0; + var cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + var u = Math.abs(psx - psy) <= 0.0001; + if (!u) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } + else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + var pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + var id = 1 / (a * d - b * c), x = cwx - pp.worldX, y = cwy - pp.worldY; + var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 0.0001) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + var dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) / 2; + var td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + var p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: if (u) { + l2 *= psx; + var cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + cos = -1; + else if (cos > 1) { + cos = 1; + if (stretch) + sx *= (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + } + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } + else { + a = psx * l2; + b = psy * l2; + var aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + var c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + var q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) / 2; + var r0 = q / c2, r1 = c / q; + var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) / 2) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + var os = Math.atan2(cy, cx) * s2; + var rotation = parent.arotation; + a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, parent.ascaleY, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * spine.MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + }; + return IkConstraint; + }()); + spine.IkConstraint = IkConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraintData = (function (_super) { + __extends(IkConstraintData, _super); + function IkConstraintData(name) { + var _this = _super.call(this, name, 0, false) || this; + _this.bones = new Array(); + _this.bendDirection = 1; + _this.compress = false; + _this.stretch = false; + _this.uniform = false; + _this.mix = 1; + _this.softness = 0; + return _this; + } + return IkConstraintData; + }(spine.ConstraintData)); + spine.IkConstraintData = IkConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraint = (function () { + function PathConstraint(data, skeleton) { + this.position = 0; + this.spacing = 0; + this.rotateMix = 0; + this.translateMix = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + this.active = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + } + PathConstraint.prototype.isActive = function () { + return this.active; + }; + PathConstraint.prototype.apply = function () { + this.update(); + }; + PathConstraint.prototype.update = function () { + var attachment = this.target.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + return; + var rotateMix = this.rotateMix, translateMix = this.translateMix; + var translate = translateMix > 0, rotate = rotateMix > 0; + if (!translate && !rotate) + return; + var data = this.data; + var percentSpacing = data.spacingMode == spine.SpacingMode.Percent; + var rotateMode = data.rotateMode; + var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale; + var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + var bones = this.bones; + var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null; + var spacing = this.spacing; + if (scale || !percentSpacing) { + if (scale) + lengths = spine.Utils.setArraySize(this.lengths, boneCount); + var lengthSpacing = data.spacingMode == spine.SpacingMode.Length; + for (var i = 0, n = spacesCount - 1; i < n;) { + var bone = bones[i]; + var setupLength = bone.data.length; + if (setupLength < PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = 0; + } + else if (percentSpacing) { + if (scale) { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_1 = Math.sqrt(x * x + y * y); + lengths[i] = length_1; + } + spaces[++i] = spacing; + } + else { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_2 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_2; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_2 / setupLength; + } + } + } + else { + for (var i = 1; i < spacesCount; i++) + spaces[i] = spacing; + } + var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, percentSpacing); + var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + var tip = false; + if (offsetRotation == 0) + tip = rotateMode == spine.RotateMode.Chain; + else { + tip = false; + var p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + } + for (var i = 0, p = 3; i < boneCount; i++, p += 3) { + var bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; + var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + var length_3 = lengths[i]; + if (length_3 != 0) { + var s = (Math.sqrt(dx * dx + dy * dy) / length_3 - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (rotate) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + var length_4 = bone.data.length; + boneX += (length_4 * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length_4 * (sin * a + cos * c) - dy) * rotateMix; + } + else { + r += offsetRotation; + } + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.appliedValid = false; + } + }; + PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) { + var target = this.target; + var position = this.position; + var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + var closed = path.closed; + var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE; + if (!path.constantSpeed) { + var lengths = path.lengths; + curveCount -= closed ? 1 : 2; + var pathLength_1 = lengths[curveCount]; + if (percentPosition) + position *= pathLength_1; + if (percentSpacing) { + for (var i = 1; i < spacesCount; i++) + spaces[i] *= pathLength_1; + } + world = spine.Utils.setArraySize(this.world, 8); + for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength_1; + if (p < 0) + p += pathLength_1; + curve = 0; + } + else if (p < 0) { + if (prevCurve != PathConstraint.BEFORE) { + prevCurve = PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength_1) { + if (prevCurve != PathConstraint.AFTER) { + prevCurve = PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength_1, world, 0, out, o); + continue; + } + for (;; curve++) { + var length_5 = lengths[curve]; + if (p > length_5) + continue; + if (curve == 0) + p /= length_5; + else { + var prev = lengths[curve - 1]; + p = (p - prev) / (length_5 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } + else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); + } + return out; + } + if (closed) { + verticesLength += 2; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else { + curveCount--; + verticesLength -= 4; + world = spine.Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + var curves = spine.Utils.setArraySize(this.curves, curveCount); + var pathLength = 0; + var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (var i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (percentPosition) + position *= pathLength; + else + position *= pathLength / path.lengths[curveCount - 1]; + if (percentSpacing) { + for (var i = 1; i < spacesCount; i++) + spaces[i] *= pathLength; + } + var segments = this.segments; + var curveLength = 0; + for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + var space = spaces[i]; + position += space; + var p = position; + if (closed) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } + else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } + else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (;; curve++) { + var length_6 = curves[curve]; + if (p > length_6) + continue; + if (curve == 0) + p /= length_6; + else { + var prev = curves[curve - 1]; + p = (p - prev) / (length_6 - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + var ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (;; segment++) { + var length_7 = segments[segment]; + if (p > length_7) + continue; + if (segment == 0) + p /= length_7; + else { + var prev = segments[segment - 1]; + p = segment + (p - prev) / (length_7 - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0)); + } + return out; + }; + PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) { + var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) { + var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + }; + PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 0.001) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + }; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + PathConstraint.epsilon = 0.00001; + return PathConstraint; + }()); + spine.PathConstraint = PathConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathConstraintData = (function (_super) { + __extends(PathConstraintData, _super); + function PathConstraintData(name) { + var _this = _super.call(this, name, 0, false) || this; + _this.bones = new Array(); + return _this; + } + return PathConstraintData; + }(spine.ConstraintData)); + spine.PathConstraintData = PathConstraintData; + var PositionMode; + (function (PositionMode) { + PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; + PositionMode[PositionMode["Percent"] = 1] = "Percent"; + })(PositionMode = spine.PositionMode || (spine.PositionMode = {})); + var SpacingMode; + (function (SpacingMode) { + SpacingMode[SpacingMode["Length"] = 0] = "Length"; + SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; + SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; + })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {})); + var RotateMode; + (function (RotateMode) { + RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; + RotateMode[RotateMode["Chain"] = 1] = "Chain"; + RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; + })(RotateMode = spine.RotateMode || (spine.RotateMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Assets = (function () { + function Assets(clientId) { + this.toLoad = new Array(); + this.assets = {}; + this.clientId = clientId; + } + Assets.prototype.loaded = function () { + var i = 0; + for (var v in this.assets) + i++; + return i; + }; + return Assets; + }()); + var SharedAssetManager = (function () { + function SharedAssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + this.clientAssets = {}; + this.queuedAssets = {}; + this.rawAssets = {}; + this.errors = {}; + this.pathPrefix = pathPrefix; + } + SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) { + clientAssets = new Assets(clientId); + this.clientAssets[clientId] = clientAssets; + } + if (textureLoader !== null) + clientAssets.textureLoader = textureLoader; + clientAssets.toLoad.push(path); + if (this.queuedAssets[path] === path) { + return false; + } + else { + this.queuedAssets[path] = path; + return true; + } + }; + SharedAssetManager.prototype.loadText = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = request.responseText; + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadJson = function (clientId, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, null, path)) + return; + var request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.onreadystatechange = function () { + if (request.readyState == XMLHttpRequest.DONE) { + if (request.status >= 200 && request.status < 300) { + _this.rawAssets[path] = JSON.parse(request.responseText); + } + else { + _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; + } + } + }; + request.open("GET", path, true); + request.send(); + }; + SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) { + var _this = this; + path = this.pathPrefix + path; + if (!this.queueAsset(clientId, textureLoader, path)) + return; + var isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document); + var isWebWorker = !isBrowser && typeof importScripts !== 'undefined'; + if (isWebWorker) { + var options = { mode: "cors" }; + fetch(path, options).then(function (response) { + if (!response.ok) { + _this.errors[path] = "Couldn't load image " + path; + } + return response.blob(); + }).then(function (blob) { + return createImageBitmap(blob, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none' + }); + }).then(function (bitmap) { + _this.rawAssets[path] = bitmap; + }); + } + else { + var img_1 = new Image(); + img_1.crossOrigin = "anonymous"; + img_1.onload = function (ev) { + _this.rawAssets[path] = img_1; + }; + img_1.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + }; + img_1.src = path; + } + }; + SharedAssetManager.prototype.get = function (clientId, path) { + path = this.pathPrefix + path; + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + return clientAssets.assets[path]; + }; + SharedAssetManager.prototype.updateClientAssets = function (clientAssets) { + var isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document); + var isWebWorker = !isBrowser && typeof importScripts !== 'undefined'; + for (var i = 0; i < clientAssets.toLoad.length; i++) { + var path = clientAssets.toLoad[i]; + var asset = clientAssets.assets[path]; + if (asset === null || asset === undefined) { + var rawAsset = this.rawAssets[path]; + if (rawAsset === null || rawAsset === undefined) + continue; + if (isWebWorker) { + if (rawAsset instanceof ImageBitmap) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + else { + if (rawAsset instanceof HTMLImageElement) { + clientAssets.assets[path] = clientAssets.textureLoader(rawAsset); + } + else { + clientAssets.assets[path] = rawAsset; + } + } + } + } + }; + SharedAssetManager.prototype.isLoadingComplete = function (clientId) { + var clientAssets = this.clientAssets[clientId]; + if (clientAssets === null || clientAssets === undefined) + return true; + this.updateClientAssets(clientAssets); + return clientAssets.toLoad.length == clientAssets.loaded(); + }; + SharedAssetManager.prototype.dispose = function () { + }; + SharedAssetManager.prototype.hasErrors = function () { + return Object.keys(this.errors).length > 0; + }; + SharedAssetManager.prototype.getErrors = function () { + return this.errors; + }; + return SharedAssetManager; + }()); + spine.SharedAssetManager = SharedAssetManager; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skeleton = (function () { + function Skeleton(data) { + this._updateCache = new Array(); + this.updateCacheReset = new Array(); + this.time = 0; + this.scaleX = 1; + this.scaleY = 1; + this.x = 0; + this.y = 0; + if (data == null) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) { + var boneData = data.bones[i]; + var bone = void 0; + if (boneData.parent == null) + bone = new spine.Bone(boneData, this, null); + else { + var parent_1 = this.bones[boneData.parent.index]; + bone = new spine.Bone(boneData, this, parent_1); + parent_1.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (var i = 0; i < data.slots.length; i++) { + var slotData = data.slots[i]; + var bone = this.bones[slotData.boneData.index]; + var slot = new spine.Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (var i = 0; i < data.ikConstraints.length; i++) { + var ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (var i = 0; i < data.transformConstraints.length; i++) { + var transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (var i = 0; i < data.pathConstraints.length; i++) { + var pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this)); + } + this.color = new spine.Color(1, 1, 1, 1); + this.updateCache(); + } + Skeleton.prototype.updateCache = function () { + var updateCache = this._updateCache; + updateCache.length = 0; + this.updateCacheReset.length = 0; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin != null) { + var skinBones = this.skin.bones; + for (var i = 0, n = this.skin.bones.length; i < n; i++) { + var bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone != null); + } + } + var ikConstraints = this.ikConstraints; + var transformConstraints = this.transformConstraints; + var pathConstraints = this.pathConstraints; + var ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + var constraintCount = ikCount + transformCount + pathCount; + outer: for (var i = 0; i < constraintCount; i++) { + for (var ii = 0; ii < ikCount; ii++) { + var constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < transformCount; ii++) { + var constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (var ii = 0; ii < pathCount; ii++) { + var constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (var i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + }; + Skeleton.prototype.sortIkConstraint = function (constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin != null && spine.Utils.contains(this.skin.constraints, constraint.data, true))); + if (!constraint.active) + return; + var target = constraint.target; + this.sortBone(target); + var constrained = constraint.bones; + var parent = constrained[0]; + this.sortBone(parent); + if (constrained.length > 1) { + var child = constrained[constrained.length - 1]; + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + this._updateCache.push(constraint); + this.sortReset(parent.children); + constrained[constrained.length - 1].sorted = true; + }; + Skeleton.prototype.sortPathConstraint = function (constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || (this.skin != null && spine.Utils.contains(this.skin.constraints, constraint.data, true))); + if (!constraint.active) + return; + var slot = constraint.target; + var slotIndex = slot.data.index; + var slotBone = slot.bone; + if (this.skin != null) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (var i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + var attachment = slot.getAttachment(); + if (attachment instanceof spine.PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + var constrained = constraint.bones; + var boneCount = constrained.length; + for (var i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (var i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (var i = 0; i < boneCount; i++) + constrained[i].sorted = true; + }; + Skeleton.prototype.sortTransformConstraint = function (constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin != null && spine.Utils.contains(this.skin.constraints, constraint.data, true))); + if (!constraint.active) + return; + this.sortBone(constraint.target); + var constrained = constraint.bones; + var boneCount = constrained.length; + if (constraint.data.local) { + for (var i = 0; i < boneCount; i++) { + var child = constrained[i]; + this.sortBone(child.parent); + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + } + else { + for (var i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (var ii = 0; ii < boneCount; ii++) + this.sortReset(constrained[ii].children); + for (var ii = 0; ii < boneCount; ii++) + constrained[ii].sorted = true; + }; + Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) { + var attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (var key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + }; + Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) { + if (!(attachment instanceof spine.PathAttachment)) + return; + var pathBones = attachment.bones; + if (pathBones == null) + this.sortBone(slotBone); + else { + var bones = this.bones; + var i = 0; + while (i < pathBones.length) { + var boneCount = pathBones[i++]; + for (var n = i + boneCount; i < n; i++) { + var boneIndex = pathBones[i]; + this.sortBone(bones[boneIndex]); + } + } + } + }; + Skeleton.prototype.sortBone = function (bone) { + if (bone.sorted) + return; + var parent = bone.parent; + if (parent != null) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + }; + Skeleton.prototype.sortReset = function (bones) { + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.active) + continue; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + }; + Skeleton.prototype.updateWorldTransform = function () { + var updateCacheReset = this.updateCacheReset; + for (var i = 0, n = updateCacheReset.length; i < n; i++) { + var bone = updateCacheReset[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + var updateCache = this._updateCache; + for (var i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + }; + Skeleton.prototype.setToSetupPose = function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }; + Skeleton.prototype.setBonesToSetupPose = function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + var data = constraint.data; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + } + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + var data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + } + }; + Skeleton.prototype.setSlotsToSetupPose = function () { + var slots = this.slots; + spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + }; + Skeleton.prototype.getRootBone = function () { + if (this.bones.length == 0) + return null; + return this.bones[0]; + }; + Skeleton.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + }; + Skeleton.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) + return i; + return -1; + }; + Skeleton.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + }; + Skeleton.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) + return i; + return -1; + }; + Skeleton.prototype.setSkinByName = function (skinName) { + var skin = this.data.findSkin(skinName); + if (skin == null) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + }; + Skeleton.prototype.setSkin = function (newSkin) { + if (newSkin == this.skin) + return; + if (newSkin != null) { + if (this.skin != null) + newSkin.attachAll(this, this.skin); + else { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var name_1 = slot.data.attachmentName; + if (name_1 != null) { + var attachment = newSkin.getAttachment(i, name_1); + if (attachment != null) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + }; + Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) { + return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName); + }; + Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) { + if (attachmentName == null) + throw new Error("attachmentName cannot be null."); + if (this.skin != null) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + return attachment; + } + if (this.data.defaultSkin != null) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }; + Skeleton.prototype.setAttachment = function (slotName, attachmentName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName != null) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + }; + Skeleton.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + }; + Skeleton.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + }; + Skeleton.prototype.getBounds = function (offset, size, temp) { + if (temp === void 0) { temp = new Array(2); } + if (offset == null) + throw new Error("offset cannot be null."); + if (size == null) + throw new Error("size cannot be null."); + var drawOrder = this.drawOrder; + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + if (!slot.bone.active) + continue; + var verticesLength = 0; + var vertices = null; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) { + verticesLength = 8; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices != null) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { + var x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + }; + Skeleton.prototype.update = function (delta) { + this.time += delta; + }; + return Skeleton; + }()); + spine.Skeleton = Skeleton; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBinary = (function () { + function SkeletonBinary(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonBinary.prototype.readSkeletonData = function (binary) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + skeletonData.name = ""; + var input = new BinaryInput(binary); + skeletonData.hash = input.readString(); + skeletonData.version = input.readString(); + if ("3.8.75" == skeletonData.version) + throw new Error("Unsupported skeleton data, please export with a newer version of Spine."); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + var nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + var n = 0; + n = input.readInt(true); + for (var i = 0; i < n; i++) + input.strings.push(input.readString()); + n = input.readInt(true); + for (var i = 0; i < n; i++) { + var name_2 = input.readString(); + var parent_2 = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + var data = new spine.BoneData(i, name_2, parent_2); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.transformMode = SkeletonBinary.TransformModeValues[input.readInt(true)]; + data.skinRequired = input.readBoolean(); + if (nonessential) + spine.Color.rgba8888ToColor(data.color, input.readInt32()); + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (var i = 0; i < n; i++) { + var slotName = input.readString(); + var boneData = skeletonData.bones[input.readInt(true)]; + var data = new spine.SlotData(i, slotName, boneData); + spine.Color.rgba8888ToColor(data.color, input.readInt32()); + var darkColor = input.readInt32(); + if (darkColor != -1) + spine.Color.rgb888ToColor(data.darkColor = new spine.Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = SkeletonBinary.BlendModeValues[input.readInt(true)]; + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (var i = 0, nn = void 0; i < n; i++) { + var data = new spine.IkConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (var ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.mix = input.readFloat(); + data.softness = input.readFloat() * scale; + data.bendDirection = input.readByte(); + data.compress = input.readBoolean(); + data.stretch = input.readBoolean(); + data.uniform = input.readBoolean(); + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (var i = 0, nn = void 0; i < n; i++) { + var data = new spine.TransformConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (var ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.local = input.readBoolean(); + data.relative = input.readBoolean(); + data.offsetRotation = input.readFloat(); + data.offsetX = input.readFloat() * scale; + data.offsetY = input.readFloat() * scale; + data.offsetScaleX = input.readFloat(); + data.offsetScaleY = input.readFloat(); + data.offsetShearY = input.readFloat(); + data.rotateMix = input.readFloat(); + data.translateMix = input.readFloat(); + data.scaleMix = input.readFloat(); + data.shearMix = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (var i = 0, nn = void 0; i < n; i++) { + var data = new spine.PathConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (var ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + data.positionMode = SkeletonBinary.PositionModeValues[input.readInt(true)]; + data.spacingMode = SkeletonBinary.SpacingModeValues[input.readInt(true)]; + data.rotateMode = SkeletonBinary.RotateModeValues[input.readInt(true)]; + data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = input.readFloat(); + data.translateMix = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + var defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin != null) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + var i = skeletonData.skins.length; + spine.Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) + skeletonData.skins[i] = this.readSkin(input, skeletonData, false, nonessential); + } + n = this.linkedMeshes.length; + for (var i = 0; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_3 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_3 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? parent_3 : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent_3); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (var i = 0; i < n; i++) { + var data = new spine.EventData(input.readStringRef()); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath != null) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (var i = 0; i < n; i++) + skeletonData.animations.push(this.readAnimation(input, input.readString(), skeletonData)); + return skeletonData; + }; + SkeletonBinary.prototype.readSkin = function (input, skeletonData, defaultSkin, nonessential) { + var skin = null; + var slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) + return null; + skin = new spine.Skin("default"); + } + else { + skin = new spine.Skin(input.readStringRef()); + skin.bones.length = input.readInt(true); + for (var i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (var i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (var i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (var i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (var i = 0; i < slotCount; i++) { + var slotIndex = input.readInt(true); + for (var ii = 0, nn = input.readInt(true); ii < nn; ii++) { + var name_3 = input.readStringRef(); + var attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name_3, nonessential); + if (attachment != null) + skin.setAttachment(slotIndex, name_3, attachment); + } + } + return skin; + }; + SkeletonBinary.prototype.readAttachment = function (input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + var scale = this.scale; + var name = input.readStringRef(); + if (name == null) + name = attachmentName; + var typeIndex = input.readByte(); + var type = SkeletonBinary.AttachmentTypeValues[typeIndex]; + switch (type) { + case spine.AttachmentType.Region: { + var path = input.readStringRef(); + var rotation = input.readFloat(); + var x = input.readFloat(); + var y = input.readFloat(); + var scaleX = input.readFloat(); + var scaleY = input.readFloat(); + var width = input.readFloat(); + var height = input.readFloat(); + var color = input.readInt32(); + if (path == null) + path = name; + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + spine.Color.rgba8888ToColor(region.color, color); + region.updateOffset(); + return region; + } + case spine.AttachmentType.BoundingBox: { + var vertexCount = input.readInt(true); + var vertices = this.readVertices(input, vertexCount); + var color = nonessential ? input.readInt32() : 0; + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + box.worldVerticesLength = vertexCount << 1; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) + spine.Color.rgba8888ToColor(box.color, color); + return box; + } + case spine.AttachmentType.Mesh: { + var path = input.readStringRef(); + var color = input.readInt32(); + var vertexCount = input.readInt(true); + var uvs = this.readFloatArray(input, vertexCount << 1, 1); + var triangles = this.readShortArray(input); + var vertices = this.readVertices(input, vertexCount); + var hullLength = input.readInt(true); + var edges = null; + var width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input); + width = input.readFloat(); + height = input.readFloat(); + } + if (path == null) + path = name; + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + spine.Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertexCount << 1; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = hullLength << 1; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case spine.AttachmentType.LinkedMesh: { + var path = input.readStringRef(); + var color = input.readInt32(); + var skinName = input.readStringRef(); + var parent_4 = input.readStringRef(); + var inheritDeform = input.readBoolean(); + var width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + if (path == null) + path = name; + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + spine.Color.rgba8888ToColor(mesh.color, color); + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinName, slotIndex, parent_4, inheritDeform)); + return mesh; + } + case spine.AttachmentType.Path: { + var closed_1 = input.readBoolean(); + var constantSpeed = input.readBoolean(); + var vertexCount = input.readInt(true); + var vertices = this.readVertices(input, vertexCount); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + var color = nonessential ? input.readInt32() : 0; + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = closed_1; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertexCount << 1; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) + spine.Color.rgba8888ToColor(path.color, color); + return path; + } + case spine.AttachmentType.Point: { + var rotation = input.readFloat(); + var x = input.readFloat(); + var y = input.readFloat(); + var color = nonessential ? input.readInt32() : 0; + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) + spine.Color.rgba8888ToColor(point.color, color); + return point; + } + case spine.AttachmentType.Clipping: { + var endSlotIndex = input.readInt(true); + var vertexCount = input.readInt(true); + var vertices = this.readVertices(input, vertexCount); + var color = nonessential ? input.readInt32() : 0; + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertexCount << 1; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) + spine.Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + }; + SkeletonBinary.prototype.readVertices = function (input, vertexCount) { + var verticesLength = vertexCount << 1; + var vertices = new Vertices(); + var scale = this.scale; + if (!input.readBoolean()) { + vertices.vertices = this.readFloatArray(input, verticesLength, scale); + return vertices; + } + var weights = new Array(); + var bonesArray = new Array(); + for (var i = 0; i < vertexCount; i++) { + var boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (var ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = spine.Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + }; + SkeletonBinary.prototype.readFloatArray = function (input, n, scale) { + var array = new Array(n); + if (scale == 1) { + for (var i = 0; i < n; i++) + array[i] = input.readFloat(); + } + else { + for (var i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + }; + SkeletonBinary.prototype.readShortArray = function (input) { + var n = input.readInt(true); + var array = new Array(n); + for (var i = 0; i < n; i++) + array[i] = input.readShort(); + return array; + }; + SkeletonBinary.prototype.readAnimation = function (input, name, skeletonData) { + var timelines = new Array(); + var scale = this.scale; + var duration = 0; + var tempColor1 = new spine.Color(); + var tempColor2 = new spine.Color(); + for (var i = 0, n = input.readInt(true); i < n; i++) { + var slotIndex = input.readInt(true); + for (var ii = 0, nn = input.readInt(true); ii < nn; ii++) { + var timelineType = input.readByte(); + var frameCount = input.readInt(true); + switch (timelineType) { + case SkeletonBinary.SLOT_ATTACHMENT: { + var timeline = new spine.AttachmentTimeline(frameCount); + timeline.slotIndex = slotIndex; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) + timeline.setFrame(frameIndex, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[frameCount - 1]); + break; + } + case SkeletonBinary.SLOT_COLOR: { + var timeline = new spine.ColorTimeline(frameCount); + timeline.slotIndex = slotIndex; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + var time = input.readFloat(); + spine.Color.rgba8888ToColor(tempColor1, input.readInt32()); + timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.ColorTimeline.ENTRIES]); + break; + } + case SkeletonBinary.SLOT_TWO_COLOR: { + var timeline = new spine.TwoColorTimeline(frameCount); + timeline.slotIndex = slotIndex; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + var time = input.readFloat(); + spine.Color.rgba8888ToColor(tempColor1, input.readInt32()); + spine.Color.rgb888ToColor(tempColor2, input.readInt32()); + timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a, tempColor2.r, tempColor2.g, tempColor2.b); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.TwoColorTimeline.ENTRIES]); + break; + } + } + } + } + for (var i = 0, n = input.readInt(true); i < n; i++) { + var boneIndex = input.readInt(true); + for (var ii = 0, nn = input.readInt(true); ii < nn; ii++) { + var timelineType = input.readByte(); + var frameCount = input.readInt(true); + switch (timelineType) { + case SkeletonBinary.BONE_ROTATE: { + var timeline = new spine.RotateTimeline(frameCount); + timeline.boneIndex = boneIndex; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat()); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.RotateTimeline.ENTRIES]); + break; + } + case SkeletonBinary.BONE_TRANSLATE: + case SkeletonBinary.BONE_SCALE: + case SkeletonBinary.BONE_SHEAR: { + var timeline = void 0; + var timelineScale = 1; + if (timelineType == SkeletonBinary.BONE_SCALE) + timeline = new spine.ScaleTimeline(frameCount); + else if (timelineType == SkeletonBinary.BONE_SHEAR) + timeline = new spine.ShearTimeline(frameCount); + else { + timeline = new spine.TranslateTimeline(frameCount); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat() * timelineScale, input.readFloat() * timelineScale); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.TranslateTimeline.ENTRIES]); + break; + } + } + } + } + for (var i = 0, n = input.readInt(true); i < n; i++) { + var index = input.readInt(true); + var frameCount = input.readInt(true); + var timeline = new spine.IkConstraintTimeline(frameCount); + timeline.ikConstraintIndex = index; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readFloat() * scale, input.readByte(), input.readBoolean(), input.readBoolean()); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + for (var i = 0, n = input.readInt(true); i < n; i++) { + var index = input.readInt(true); + var frameCount = input.readInt(true); + var timeline = new spine.TransformConstraintTimeline(frameCount); + timeline.transformConstraintIndex = index; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + for (var i = 0, n = input.readInt(true); i < n; i++) { + var index = input.readInt(true); + var data = skeletonData.pathConstraints[index]; + for (var ii = 0, nn = input.readInt(true); ii < nn; ii++) { + var timelineType = input.readByte(); + var frameCount = input.readInt(true); + switch (timelineType) { + case SkeletonBinary.PATH_POSITION: + case SkeletonBinary.PATH_SPACING: { + var timeline = void 0; + var timelineScale = 1; + if (timelineType == SkeletonBinary.PATH_SPACING) { + timeline = new spine.PathConstraintSpacingTimeline(frameCount); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(frameCount); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat() * timelineScale); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + break; + } + case SkeletonBinary.PATH_MIX: { + var timeline = new spine.PathConstraintMixTimeline(frameCount); + timeline.pathConstraintIndex = index; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readFloat()); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(frameCount - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + break; + } + } + } + } + for (var i = 0, n = input.readInt(true); i < n; i++) { + var skin = skeletonData.skins[input.readInt(true)]; + for (var ii = 0, nn = input.readInt(true); ii < nn; ii++) { + var slotIndex = input.readInt(true); + for (var iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + var attachment = skin.getAttachment(slotIndex, input.readStringRef()); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var frameCount = input.readInt(true); + var timeline = new spine.DeformTimeline(frameCount); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + for (var frameIndex = 0; frameIndex < frameCount; frameIndex++) { + var time = input.readFloat(); + var deform = void 0; + var end = input.readInt(true); + if (end == 0) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = input.readInt(true); + end += start; + if (scale == 1) { + for (var v = start; v < end; v++) + deform[v] = input.readFloat(); + } + else { + for (var v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (var v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frameIndex, time, deform); + if (frameIndex < frameCount - 1) + this.readCurve(input, frameIndex, timeline); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[frameCount - 1]); + } + } + } + var drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + var timeline = new spine.DrawOrderTimeline(drawOrderCount); + var slotCount = skeletonData.slots.length; + for (var i = 0; i < drawOrderCount; i++) { + var time = input.readFloat(); + var offsetCount = input.readInt(true); + var drawOrder = spine.Utils.newArray(slotCount, 0); + for (var ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + var unchanged = spine.Utils.newArray(slotCount - offsetCount, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var ii = 0; ii < offsetCount; ii++) { + var slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[drawOrderCount - 1]); + } + var eventCount = input.readInt(true); + if (eventCount > 0) { + var timeline = new spine.EventTimeline(eventCount); + for (var i = 0; i < eventCount; i++) { + var time = input.readFloat(); + var eventData = skeletonData.events[input.readInt(true)]; + var event_4 = new spine.Event(time, eventData); + event_4.intValue = input.readInt(false); + event_4.floatValue = input.readFloat(); + event_4.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; + if (event_4.data.audioPath != null) { + event_4.volume = input.readFloat(); + event_4.balance = input.readFloat(); + } + timeline.setFrame(i, event_4); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[eventCount - 1]); + } + return new spine.Animation(name, timelines, duration); + }; + SkeletonBinary.prototype.readCurve = function (input, frameIndex, timeline) { + switch (input.readByte()) { + case SkeletonBinary.CURVE_STEPPED: + timeline.setStepped(frameIndex); + break; + case SkeletonBinary.CURVE_BEZIER: + this.setCurve(timeline, frameIndex, input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); + break; + } + }; + SkeletonBinary.prototype.setCurve = function (timeline, frameIndex, cx1, cy1, cx2, cy2) { + timeline.setCurve(frameIndex, cx1, cy1, cx2, cy2); + }; + SkeletonBinary.AttachmentTypeValues = [0, 1, 2, 3, 4, 5, 6]; + SkeletonBinary.TransformModeValues = [spine.TransformMode.Normal, spine.TransformMode.OnlyTranslation, spine.TransformMode.NoRotationOrReflection, spine.TransformMode.NoScale, spine.TransformMode.NoScaleOrReflection]; + SkeletonBinary.PositionModeValues = [spine.PositionMode.Fixed, spine.PositionMode.Percent]; + SkeletonBinary.SpacingModeValues = [spine.SpacingMode.Length, spine.SpacingMode.Fixed, spine.SpacingMode.Percent]; + SkeletonBinary.RotateModeValues = [spine.RotateMode.Tangent, spine.RotateMode.Chain, spine.RotateMode.ChainScale]; + SkeletonBinary.BlendModeValues = [spine.BlendMode.Normal, spine.BlendMode.Additive, spine.BlendMode.Multiply, spine.BlendMode.Screen]; + SkeletonBinary.BONE_ROTATE = 0; + SkeletonBinary.BONE_TRANSLATE = 1; + SkeletonBinary.BONE_SCALE = 2; + SkeletonBinary.BONE_SHEAR = 3; + SkeletonBinary.SLOT_ATTACHMENT = 0; + SkeletonBinary.SLOT_COLOR = 1; + SkeletonBinary.SLOT_TWO_COLOR = 2; + SkeletonBinary.PATH_POSITION = 0; + SkeletonBinary.PATH_SPACING = 1; + SkeletonBinary.PATH_MIX = 2; + SkeletonBinary.CURVE_LINEAR = 0; + SkeletonBinary.CURVE_STEPPED = 1; + SkeletonBinary.CURVE_BEZIER = 2; + return SkeletonBinary; + }()); + spine.SkeletonBinary = SkeletonBinary; + var BinaryInput = (function () { + function BinaryInput(data, strings, index, buffer) { + if (strings === void 0) { strings = new Array(); } + if (index === void 0) { index = 0; } + if (buffer === void 0) { buffer = new DataView(data.buffer); } + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + BinaryInput.prototype.readByte = function () { + return this.buffer.getInt8(this.index++); + }; + BinaryInput.prototype.readShort = function () { + var value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + }; + BinaryInput.prototype.readInt32 = function () { + var value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + }; + BinaryInput.prototype.readInt = function (optimizePositive) { + var b = this.readByte(); + var result = b & 0x7F; + if ((b & 0x80) != 0) { + b = this.readByte(); + result |= (b & 0x7F) << 7; + if ((b & 0x80) != 0) { + b = this.readByte(); + result |= (b & 0x7F) << 14; + if ((b & 0x80) != 0) { + b = this.readByte(); + result |= (b & 0x7F) << 21; + if ((b & 0x80) != 0) { + b = this.readByte(); + result |= (b & 0x7F) << 28; + } + } + } + } + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + }; + BinaryInput.prototype.readStringRef = function () { + var index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + }; + BinaryInput.prototype.readString = function () { + var byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + var chars = ""; + var charCount = 0; + for (var i = 0; i < byteCount;) { + var b = this.readByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode(((b & 0x1F) << 6 | this.readByte() & 0x3F)); + i += 2; + break; + case 14: + chars += String.fromCharCode(((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F)); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + }; + BinaryInput.prototype.readFloat = function () { + var value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + }; + BinaryInput.prototype.readBoolean = function () { + return this.readByte() != 0; + }; + return BinaryInput; + }()); + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritDeform = inheritDeform; + } + return LinkedMesh; + }()); + var Vertices = (function () { + function Vertices(bones, vertices) { + if (bones === void 0) { bones = null; } + if (vertices === void 0) { vertices = null; } + this.bones = bones; + this.vertices = vertices; + } + return Vertices; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonBounds = (function () { + function SkeletonBounds() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new spine.Pool(function () { + return spine.Utils.newFloatArray(16); + }); + } + SkeletonBounds.prototype.update = function (skeleton, updateAabb) { + if (skeleton == null) + throw new Error("skeleton cannot be null."); + var boundingBoxes = this.boundingBoxes; + var polygons = this.polygons; + var polygonPool = this.polygonPool; + var slots = skeleton.slots; + var slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (var i = 0; i < slotCount; i++) { + var slot = slots[i]; + if (!slot.bone.active) + continue; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.BoundingBoxAttachment) { + var boundingBox = attachment; + boundingBoxes.push(boundingBox); + var polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } + else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + }; + SkeletonBounds.prototype.aabbCompute = function () { + var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + var vertices = polygon; + for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) { + var x = vertices[ii]; + var y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + }; + SkeletonBounds.prototype.aabbContainsPoint = function (x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + }; + SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) { + var minX = this.minX; + var minY = this.minY; + var maxX = this.maxX; + var maxY = this.maxY; + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + return false; + var m = (y2 - y1) / (x2 - x1); + var y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + var x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + }; + SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + }; + SkeletonBounds.prototype.containsPoint = function (x, y) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) { + var vertices = polygon; + var nn = polygon.length; + var prevIndex = nn - 2; + var inside = false; + for (var ii = 0; ii < nn; ii += 2) { + var vertexY = vertices[ii + 1]; + var prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { + var vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + }; + SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) { + var polygons = this.polygons; + for (var i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + }; + SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) { + var vertices = polygon; + var nn = polygon.length; + var width12 = x1 - x2, height12 = y1 - y2; + var det1 = x1 * y2 - y1 * x2; + var x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (var ii = 0; ii < nn; ii += 2) { + var x4 = vertices[ii], y4 = vertices[ii + 1]; + var det2 = x3 * y4 - y3 * x4; + var width34 = x3 - x4, height34 = y3 - y4; + var det3 = width12 * height34 - height12 * width34; + var x = (det1 * width34 - width12 * det2) / det3; + if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { + var y = (det1 * height34 - height12 * det2) / det3; + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + }; + SkeletonBounds.prototype.getPolygon = function (boundingBox) { + if (boundingBox == null) + throw new Error("boundingBox cannot be null."); + var index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + }; + SkeletonBounds.prototype.getWidth = function () { + return this.maxX - this.minX; + }; + SkeletonBounds.prototype.getHeight = function () { + return this.maxY - this.minY; + }; + return SkeletonBounds; + }()); + spine.SkeletonBounds = SkeletonBounds; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonClipping = (function () { + function SkeletonClipping() { + this.triangulator = new spine.Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + SkeletonClipping.prototype.clipStart = function (slot, clip) { + if (this.clipAttachment != null) + return 0; + this.clipAttachment = clip; + var n = clip.worldVerticesLength; + var vertices = spine.Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + var clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (var i = 0, n_2 = clippingPolygons.length; i < n_2; i++) { + var polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + }; + SkeletonClipping.prototype.clipEndWithSlot = function (slot) { + if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + }; + SkeletonClipping.prototype.clipEnd = function () { + if (this.clipAttachment == null) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + }; + SkeletonClipping.prototype.isClipping = function () { + return this.clipAttachment != null; + }; + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + var clippedTriangles = this.clippedTriangles; + var polygons = this.clippingPolygons; + var polygonsCount = this.clippingPolygons.length; + var vertexSize = twoColor ? 12 : 8; + var index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: for (var i = 0; i < trianglesLength; i += 3) { + var vertexOffset = triangles[i] << 1; + var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { + var s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + var clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + var d = 1 / (d0 * d2 + d1 * (y1 - y3)); + var clipOutputCount = clipOutputLength >> 1; + var clipOutputItems = this.clipOutput; + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (var ii = 0; ii < clipOutputLength; ii += 2) { + var x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + var c0 = x - x3, c1 = y - y3; + var a = (d0 * c0 + d1 * c1) * d; + var b = (d4 * c0 + d2 * c1) * d; + var c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (var ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + ii); + clippedTrianglesItems[s + 2] = (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } + else { + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } + else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + 1); + clippedTrianglesItems[s + 2] = (index + 2); + index += 3; + continue outer; + } + } + } + }; + SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) { + var originalOutput = output; + var clipped = false; + var input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } + else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + var clippingVertices = clippingArea; + var clippingVerticesLast = clippingArea.length - 4; + for (var i = 0;; i += 2) { + var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + var inputVertices = input; + var inputVerticesLength = input.length - 2, outputStart = output.length; + for (var ii = 0; ii < inputVerticesLength; ii += 2) { + var inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 0.000001) { + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else { + output.push(edgeX); + output.push(edgeY); + } + } + else if (side2) { + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 0.000001) { + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else { + output.push(edgeX); + output.push(edgeY); + } + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + var temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (var i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } + else + originalOutput.length = originalOutput.length - 2; + return clipped; + }; + SkeletonClipping.makeClockwise = function (polygon) { + var vertices = polygon; + var verticeslength = polygon.length; + var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (var i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + var x = vertices[i], y = vertices[i + 1]; + var other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + }; + return SkeletonClipping; + }()); + spine.SkeletonClipping = SkeletonClipping; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonData = (function () { + function SkeletonData() { + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + this.fps = 0; + } + SkeletonData.prototype.findBone = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + }; + SkeletonData.prototype.findBoneIndex = function (boneName) { + if (boneName == null) + throw new Error("boneName cannot be null."); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) + return i; + return -1; + }; + SkeletonData.prototype.findSlot = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + }; + SkeletonData.prototype.findSlotIndex = function (slotName) { + if (slotName == null) + throw new Error("slotName cannot be null."); + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) + return i; + return -1; + }; + SkeletonData.prototype.findSkin = function (skinName) { + if (skinName == null) + throw new Error("skinName cannot be null."); + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) { + var skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + }; + SkeletonData.prototype.findEvent = function (eventDataName) { + if (eventDataName == null) + throw new Error("eventDataName cannot be null."); + var events = this.events; + for (var i = 0, n = events.length; i < n; i++) { + var event_5 = events[i]; + if (event_5.name == eventDataName) + return event_5; + } + return null; + }; + SkeletonData.prototype.findAnimation = function (animationName) { + if (animationName == null) + throw new Error("animationName cannot be null."); + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) { + var animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + }; + SkeletonData.prototype.findIkConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var ikConstraints = this.ikConstraints; + for (var i = 0, n = ikConstraints.length; i < n; i++) { + var constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findTransformConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var transformConstraints = this.transformConstraints; + for (var i = 0, n = transformConstraints.length; i < n; i++) { + var constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraint = function (constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) { + var constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + }; + SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) { + if (pathConstraintName == null) + throw new Error("pathConstraintName cannot be null."); + var pathConstraints = this.pathConstraints; + for (var i = 0, n = pathConstraints.length; i < n; i++) + if (pathConstraints[i].name == pathConstraintName) + return i; + return -1; + }; + return SkeletonData; + }()); + spine.SkeletonData = SkeletonData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkeletonJson = (function () { + function SkeletonJson(attachmentLoader) { + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + SkeletonJson.prototype.readSkeletonData = function (json) { + var scale = this.scale; + var skeletonData = new spine.SkeletonData(); + var root = typeof (json) === "string" ? JSON.parse(json) : json; + var skeletonMap = root.skeleton; + if (skeletonMap != null) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + if ("3.8.75" == skeletonData.version) + throw new Error("Unsupported skeleton data, please export with a newer version of Spine."); + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (var i = 0; i < root.bones.length; i++) { + var boneMap = root.bones[i]; + var parent_5 = null; + var parentName = this.getValue(boneMap, "parent", null); + if (parentName != null) { + parent_5 = skeletonData.findBone(parentName); + if (parent_5 == null) + throw new Error("Parent bone not found: " + parentName); + } + var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_5); + data.length = this.getValue(boneMap, "length", 0) * scale; + data.x = this.getValue(boneMap, "x", 0) * scale; + data.y = this.getValue(boneMap, "y", 0) * scale; + data.rotation = this.getValue(boneMap, "rotation", 0); + data.scaleX = this.getValue(boneMap, "scaleX", 1); + data.scaleY = this.getValue(boneMap, "scaleY", 1); + data.shearX = this.getValue(boneMap, "shearX", 0); + data.shearY = this.getValue(boneMap, "shearY", 0); + data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, "transform", "normal")); + data.skinRequired = this.getValue(boneMap, "skin", false); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (var i = 0; i < root.slots.length; i++) { + var slotMap = root.slots[i]; + var slotName = slotMap.name; + var boneName = slotMap.bone; + var boneData = skeletonData.findBone(boneName); + if (boneData == null) + throw new Error("Slot bone not found: " + boneName); + var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData); + var color = this.getValue(slotMap, "color", null); + if (color != null) + data.color.setFromString(color); + var dark = this.getValue(slotMap, "dark", null); + if (dark != null) { + data.darkColor = new spine.Color(1, 1, 1, 1); + data.darkColor.setFromString(dark); + } + data.attachmentName = this.getValue(slotMap, "attachment", null); + data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (var i = 0; i < root.ik.length; i++) { + var constraintMap = root.ik[i]; + var data = new spine.IkConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + data.skinRequired = this.getValue(constraintMap, "skin", false); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("IK bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("IK target bone not found: " + targetName); + data.mix = this.getValue(constraintMap, "mix", 1); + data.softness = this.getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = this.getValue(constraintMap, "compress", false); + data.stretch = this.getValue(constraintMap, "stretch", false); + data.uniform = this.getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (var i = 0; i < root.transform.length; i++) { + var constraintMap = root.transform[i]; + var data = new spine.TransformConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + data.skinRequired = this.getValue(constraintMap, "skin", false); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + if (data.target == null) + throw new Error("Transform constraint target bone not found: " + targetName); + data.local = this.getValue(constraintMap, "local", false); + data.relative = this.getValue(constraintMap, "relative", false); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.offsetX = this.getValue(constraintMap, "x", 0) * scale; + data.offsetY = this.getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0); + data.offsetShearY = this.getValue(constraintMap, "shearY", 0); + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + data.scaleMix = this.getValue(constraintMap, "scaleMix", 1); + data.shearMix = this.getValue(constraintMap, "shearMix", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (var i = 0; i < root.path.length; i++) { + var constraintMap = root.path[i]; + var data = new spine.PathConstraintData(constraintMap.name); + data.order = this.getValue(constraintMap, "order", 0); + data.skinRequired = this.getValue(constraintMap, "skin", false); + for (var j = 0; j < constraintMap.bones.length; j++) { + var boneName = constraintMap.bones[j]; + var bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Transform constraint bone not found: " + boneName); + data.bones.push(bone); + } + var targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + if (data.target == null) + throw new Error("Path target slot not found: " + targetName); + data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent")); + data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length")); + data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent")); + data.offsetRotation = this.getValue(constraintMap, "rotation", 0); + data.position = this.getValue(constraintMap, "position", 0); + if (data.positionMode == spine.PositionMode.Fixed) + data.position *= scale; + data.spacing = this.getValue(constraintMap, "spacing", 0); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + data.spacing *= scale; + data.rotateMix = this.getValue(constraintMap, "rotateMix", 1); + data.translateMix = this.getValue(constraintMap, "translateMix", 1); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (var i = 0; i < root.skins.length; i++) { + var skinMap = root.skins[i]; + var skin = new spine.Skin(skinMap.name); + if (skinMap.bones) { + for (var ii = 0; ii < skinMap.bones.length; ii++) { + var bone = skeletonData.findBone(skinMap.bones[ii]); + if (bone == null) + throw new Error("Skin bone not found: " + skinMap.bones[i]); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (var ii = 0; ii < skinMap.ik.length; ii++) { + var constraint = skeletonData.findIkConstraint(skinMap.ik[ii]); + if (constraint == null) + throw new Error("Skin IK constraint not found: " + skinMap.ik[i]); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (var ii = 0; ii < skinMap.transform.length; ii++) { + var constraint = skeletonData.findTransformConstraint(skinMap.transform[ii]); + if (constraint == null) + throw new Error("Skin transform constraint not found: " + skinMap.transform[i]); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (var ii = 0; ii < skinMap.path.length; ii++) { + var constraint = skeletonData.findPathConstraint(skinMap.path[ii]); + if (constraint == null) + throw new Error("Skin path constraint not found: " + skinMap.path[i]); + skin.constraints.push(constraint); + } + } + for (var slotName in skinMap.attachments) { + var slot = skeletonData.findSlot(slotName); + if (slot == null) + throw new Error("Slot not found: " + slotName); + var slotMap = skinMap.attachments[slotName]; + for (var entryName in slotMap) { + var attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment != null) + skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (var i = 0, n = this.linkedMeshes.length; i < n; i++) { + var linkedMesh = this.linkedMeshes[i]; + var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) + throw new Error("Skin not found: " + linkedMesh.skin); + var parent_6 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (parent_6 == null) + throw new Error("Parent mesh not found: " + linkedMesh.parent); + linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? parent_6 : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent_6); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (var eventName in root.events) { + var eventMap = root.events[eventName]; + var data = new spine.EventData(eventName); + data.intValue = this.getValue(eventMap, "int", 0); + data.floatValue = this.getValue(eventMap, "float", 0); + data.stringValue = this.getValue(eventMap, "string", ""); + data.audioPath = this.getValue(eventMap, "audio", null); + if (data.audioPath != null) { + data.volume = this.getValue(eventMap, "volume", 1); + data.balance = this.getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (var animationName in root.animations) { + var animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + }; + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) { + var scale = this.scale; + name = this.getValue(map, "name", name); + var type = this.getValue(map, "type", "region"); + switch (type) { + case "region": { + var path = this.getValue(map, "path", name); + var region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (region == null) + return null; + region.path = path; + region.x = this.getValue(map, "x", 0) * scale; + region.y = this.getValue(map, "y", 0) * scale; + region.scaleX = this.getValue(map, "scaleX", 1); + region.scaleY = this.getValue(map, "scaleY", 1); + region.rotation = this.getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + var color = this.getValue(map, "color", null); + if (color != null) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (box == null) + return null; + this.readVertices(map, box, map.vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + var path = this.getValue(map, "path", name); + var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) + return null; + mesh.path = path; + var color = this.getValue(map, "color", null); + if (color != null) + mesh.color.setFromString(color); + mesh.width = this.getValue(map, "width", 0) * scale; + mesh.height = this.getValue(map, "height", 0) * scale; + var parent_7 = this.getValue(map, "parent", null); + if (parent_7 != null) { + this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_7, this.getValue(map, "deform", true))); + return mesh; + } + var uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.edges = this.getValue(map, "edges", null); + mesh.hullLength = this.getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + var path = this.attachmentLoader.newPathAttachment(skin, name); + if (path == null) + return null; + path.closed = this.getValue(map, "closed", false); + path.constantSpeed = this.getValue(map, "constantSpeed", true); + var vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + var lengths = spine.Utils.newArray(vertexCount / 3, 0); + for (var i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + var color = this.getValue(map, "color", null); + if (color != null) + path.color.setFromString(color); + return path; + } + case "point": { + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = this.getValue(map, "x", 0) * scale; + point.y = this.getValue(map, "y", 0) * scale; + point.rotation = this.getValue(map, "rotation", 0); + var color = this.getValue(map, "color", null); + if (color != null) + point.color.setFromString(color); + return point; + } + case "clipping": { + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + var end = this.getValue(map, "end", null); + if (end != null) { + var slot = skeletonData.findSlot(end); + if (slot == null) + throw new Error("Clipping end slot not found: " + end); + clip.endSlot = slot; + } + var vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + clip.color.setFromString(color); + return clip; + } + } + return null; + }; + SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) { + var scale = this.scale; + attachment.worldVerticesLength = verticesLength; + var vertices = map.vertices; + if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); + if (scale != 1) { + for (var i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + var weights = new Array(); + var bones = new Array(); + for (var i = 0, n = vertices.length; i < n;) { + var boneCount = vertices[i++]; + bones.push(boneCount); + for (var nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = spine.Utils.toFloatArray(weights); + }; + SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) { + var scale = this.scale; + var timelines = new Array(); + var duration = 0; + if (map.slots) { + for (var slotName in map.slots) { + var slotMap = map.slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotName); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, this.getValue(valueMap, "time", 0), valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else if (timelineName == "color") { + var timeline = new spine.ColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var color = new spine.Color(); + color.setFromString(valueMap.color); + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), color.r, color.g, color.b, color.a); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); + } + else if (timelineName == "twoColor") { + var timeline = new spine.TwoColorTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var light = new spine.Color(); + var dark = new spine.Color(); + light.setFromString(valueMap.light); + dark.setFromString(valueMap.dark); + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + if (map.bones) { + for (var boneName in map.bones) { + var boneMap = map.bones[boneName]; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) + throw new Error("Bone not found: " + boneName); + for (var timelineName in boneMap) { + var timelineMap = boneMap[timelineName]; + if (timelineName === "rotate") { + var timeline = new spine.RotateTimeline(timelineMap.length); + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), this.getValue(valueMap, "angle", 0)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]); + } + else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") { + var timeline = null; + var timelineScale = 1, defaultValue = 0; + if (timelineName === "scale") { + timeline = new spine.ScaleTimeline(timelineMap.length); + defaultValue = 1; + } + else if (timelineName === "shear") + timeline = new spine.ShearTimeline(timelineMap.length); + else { + timeline = new spine.TranslateTimeline(timelineMap.length); + timelineScale = scale; + } + timeline.boneIndex = boneIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + var x = this.getValue(valueMap, "x", defaultValue), y = this.getValue(valueMap, "y", defaultValue); + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), x * timelineScale, y * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]); + } + else + throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); + } + } + } + if (map.ik) { + for (var constraintName in map.ik) { + var constraintMap = map.ik[constraintName]; + var constraint = skeletonData.findIkConstraint(constraintName); + var timeline = new spine.IkConstraintTimeline(constraintMap.length); + timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "softness", 0) * scale, this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "compress", false), this.getValue(valueMap, "stretch", false)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]); + } + } + if (map.transform) { + for (var constraintName in map.transform) { + var constraintMap = map.transform[constraintName]; + var constraint = skeletonData.findTransformConstraint(constraintName); + var timeline = new spine.TransformConstraintTimeline(constraintMap.length); + timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint); + var frameIndex = 0; + for (var i = 0; i < constraintMap.length; i++) { + var valueMap = constraintMap[i]; + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]); + } + } + if (map.path) { + for (var constraintName in map.path) { + var constraintMap = map.path[constraintName]; + var index = skeletonData.findPathConstraintIndex(constraintName); + if (index == -1) + throw new Error("Path constraint not found: " + constraintName); + var data = skeletonData.pathConstraints[index]; + for (var timelineName in constraintMap) { + var timelineMap = constraintMap[timelineName]; + if (timelineName === "position" || timelineName === "spacing") { + var timeline = null; + var timelineScale = 1; + if (timelineName === "spacing") { + timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length); + if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed) + timelineScale = scale; + } + else { + timeline = new spine.PathConstraintPositionTimeline(timelineMap.length); + if (data.positionMode == spine.PositionMode.Fixed) + timelineScale = scale; + } + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), this.getValue(valueMap, timelineName, 0) * timelineScale); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]); + } + else if (timelineName === "mix") { + var timeline = new spine.PathConstraintMixTimeline(timelineMap.length); + timeline.pathConstraintIndex = index; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1)); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]); + } + } + } + } + if (map.deform) { + for (var deformName in map.deform) { + var deformMap = map.deform[deformName]; + var skin = skeletonData.findSkin(deformName); + if (skin == null) + throw new Error("Skin not found: " + deformName); + for (var slotName in deformMap) { + var slotMap = deformMap[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + if (slotIndex == -1) + throw new Error("Slot not found: " + slotMap.name); + for (var timelineName in slotMap) { + var timelineMap = slotMap[timelineName]; + var attachment = skin.getAttachment(slotIndex, timelineName); + if (attachment == null) + throw new Error("Deform attachment not found: " + timelineMap.name); + var weighted = attachment.bones != null; + var vertices = attachment.vertices; + var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + var timeline = new spine.DeformTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + timeline.attachment = attachment; + var frameIndex = 0; + for (var j = 0; j < timelineMap.length; j++) { + var valueMap = timelineMap[j]; + var deform = void 0; + var verticesValue = this.getValue(valueMap, "vertices", null); + if (verticesValue == null) + deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices; + else { + deform = spine.Utils.newFloatArray(deformLength); + var start = this.getValue(valueMap, "offset", 0); + spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (var i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (var i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frameIndex, this.getValue(valueMap, "time", 0), deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, this.getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_6 = new spine.Event(spine.Utils.toSinglePrecision(this.getValue(eventMap, "time", 0)), eventData); + event_6.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_6.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_6.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + if (event_6.data.audioPath != null) { + event_6.volume = this.getValue(eventMap, "volume", 1); + event_6.balance = this.getValue(eventMap, "balance", 0); + } + timeline.setFrame(frameIndex++, event_6); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.hasOwnProperty("curve")) + return; + if (map.curve == "stepped") + timeline.setStepped(frameIndex); + else { + var curve = map.curve; + timeline.setCurve(frameIndex, curve, this.getValue(map, "c2", 0), this.getValue(map, "c3", 1), this.getValue(map, "c4", 1)); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + SkeletonJson.transformModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.TransformMode.Normal; + if (str == "onlytranslation") + return spine.TransformMode.OnlyTranslation; + if (str == "norotationorreflection") + return spine.TransformMode.NoRotationOrReflection; + if (str == "noscale") + return spine.TransformMode.NoScale; + if (str == "noscaleorreflection") + return spine.TransformMode.NoScaleOrReflection; + throw new Error("Unknown transform mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritDeform = inheritDeform; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var SkinEntry = (function () { + function SkinEntry(slotIndex, name, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + return SkinEntry; + }()); + spine.SkinEntry = SkinEntry; + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + this.bones = Array(); + this.constraints = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.setAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.addSkin = function (skin) { + for (var i = 0; i < skin.bones.length; i++) { + var bone = skin.bones[i]; + var contained = false; + for (var j = 0; j < this.bones.length; j++) { + if (this.bones[j] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (var i = 0; i < skin.constraints.length; i++) { + var constraint = skin.constraints[i]; + var contained = false; + for (var j = 0; j < this.constraints.length; j++) { + if (this.constraints[j] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + var attachments = skin.getAttachments(); + for (var i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + }; + Skin.prototype.copySkin = function (skin) { + for (var i = 0; i < skin.bones.length; i++) { + var bone = skin.bones[i]; + var contained = false; + for (var j = 0; j < this.bones.length; j++) { + if (this.bones[j] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (var i = 0; i < skin.constraints.length; i++) { + var constraint = skin.constraints[i]; + var contained = false; + for (var j = 0; j < this.constraints.length; j++) { + if (this.constraints[j] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + var attachments = skin.getAttachments(); + for (var i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (attachment.attachment == null) + continue; + if (attachment.attachment instanceof spine.MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.removeAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + if (dictionary) + dictionary[name] = null; + }; + Skin.prototype.getAttachments = function () { + var entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + var slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (var name_4 in slotAttachments) { + var attachment = slotAttachments[name_4]; + if (attachment) + entries.push(new SkinEntry(i, name_4, attachment)); + } + } + } + return entries; + }; + Skin.prototype.getAttachmentsForSlot = function (slotIndex, attachments) { + var slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (var name_5 in slotAttachments) { + var attachment = slotAttachments[name_5]; + if (attachment) + attachments.push(new SkinEntry(slotIndex, name_5, attachment)); + } + } + }; + Skin.prototype.clear = function () { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.deform = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.darkColor = data.darkColor == null ? null : new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getSkeleton = function () { + return this.bone.skeleton; + }; + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.deform.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.darkColor != null) + this.darkColor.setFromColor(this.data.darkColor); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + var TextureFilter; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {})); + var TextureWrap; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {})); + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; + var FakeTexture = (function (_super) { + __extends(FakeTexture, _super); + function FakeTexture() { + return _super !== null && _super.apply(this, arguments) || this; + } + FakeTexture.prototype.setFilters = function (minFilter, magFilter) { }; + FakeTexture.prototype.setWraps = function (uWrap, vWrap) { }; + FakeTexture.prototype.dispose = function () { }; + return FakeTexture; + }(Texture)); + spine.FakeTexture = FakeTexture; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + var rotateValue = reader.readValue(); + if (rotateValue.toLocaleLowerCase() == "true") { + region.degrees = 90; + } + else if (rotateValue.toLocaleLowerCase() == "false") { + region.degrees = 0; + } + else { + region.degrees = parseFloat(rotateValue); + } + region.rotate = region.degrees == 90; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + return _super !== null && _super.apply(this, arguments) || this; + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + this.active = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.isActive = function () { + return this.active; + }; + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } + else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + }; + TransformConstraint.prototype.applyAbsoluteWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect; + var offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; + bone.a *= s; + bone.c *= s; + s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyRelativeWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * translateMix; + bone.worldY += temp.y * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + var b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyAbsoluteLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) { + var r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + var shearY = bone.ashearY; + if (shearMix != 0) { + var r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.applyRelativeLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) + rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix != 0) { + if (scaleX > 0.00001) + scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) + scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + var shearY = bone.ashearY; + if (shearMix != 0) + shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function (_super) { + __extends(TransformConstraintData, _super); + function TransformConstraintData(name) { + var _this = _super.call(this, name, 0, false) || this; + _this.bones = new Array(); + _this.rotateMix = 0; + _this.translateMix = 0; + _this.scaleMix = 0; + _this.shearMix = 0; + _this.offsetRotation = 0; + _this.offsetX = 0; + _this.offsetY = 0; + _this.offsetScaleX = 0; + _this.offsetScaleY = 0; + _this.offsetShearY = 0; + _this.relative = false; + _this.local = false; + return _this; + } + return TransformConstraintData; + }(spine.ConstraintData)); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Triangulator = (function () { + function Triangulator() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new spine.Pool(function () { + return new Array(); + }); + this.polygonIndicesPool = new spine.Pool(function () { + return new Array(); + }); + } + Triangulator.prototype.triangulate = function (verticesArray) { + var vertices = verticesArray; + var vertexCount = verticesArray.length >> 1; + var indices = this.indicesArray; + indices.length = 0; + for (var i = 0; i < vertexCount; i++) + indices[i] = i; + var isConcave = this.isConcaveArray; + isConcave.length = 0; + for (var i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + var triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + var previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: if (!isConcave[i]) { + var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + var p1x = vertices[p1], p1y = vertices[p1 + 1]; + var p2x = vertices[p2], p2y = vertices[p2 + 1]; + var p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + var v = indices[ii] << 1; + var vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + var previousIndex = (vertexCount + i - 1) % vertexCount; + var nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + }; + Triangulator.prototype.decompose = function (verticesArray, triangles) { + var vertices = verticesArray; + var convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + var convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + var polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + var polygon = this.polygonPool.obtain(); + polygon.length = 0; + var fanBaseIndex = -1, lastWinding = 0; + for (var i = 0, n = triangles.length; i < n; i += 3) { + var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + var x1 = vertices[t1], y1 = vertices[t1 + 1]; + var x2 = vertices[t2], y2 = vertices[t2 + 1]; + var x3 = vertices[t3], y3 = vertices[t3 + 1]; + var merged = false; + if (fanBaseIndex == t1) { + var o = polygon.length - 4; + var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (var i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + var firstIndex = polygonIndices[0]; + var lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + var o = polygon.length - 4; + var prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + var prevX = polygon[o + 2], prevY = polygon[o + 3]; + var firstX = polygon[0], firstY = polygon[1]; + var secondX = polygon[2], secondY = polygon[3]; + var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (var ii = 0; ii < n; ii++) { + if (ii == i) + continue; + var otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + var otherFirstIndex = otherIndices[0]; + var otherSecondIndex = otherIndices[1]; + var otherLastIndex = otherIndices[2]; + var otherPoly = convexPolygons[ii]; + var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (var i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + }; + Triangulator.isConcave = function (index, vertexCount, vertices, indices) { + var previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + var current = indices[index] << 1; + var next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); + }; + Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + }; + Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) { + var px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + }; + return Triangulator; + }()); + spine.Triangulator = Triangulator; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IntSet = (function () { + function IntSet() { + this.array = new Array(); + } + IntSet.prototype.add = function (value) { + var contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + }; + IntSet.prototype.contains = function (value) { + return this.array[value | 0] != undefined; + }; + IntSet.prototype.remove = function (value) { + this.array[value | 0] = undefined; + }; + IntSet.prototype.clear = function () { + this.array.length = 0; + }; + return IntSet; + }()); + spine.IntSet = IntSet; + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + }; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + }; + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + }; + Color.rgba8888ToColor = function (color, value) { + color.r = ((value & 0xff000000) >>> 24) / 255; + color.g = ((value & 0x00ff0000) >>> 16) / 255; + color.b = ((value & 0x0000ff00) >>> 8) / 255; + color.a = ((value & 0x000000ff)) / 255; + }; + Color.rgb888ToColor = function (color, value) { + color.r = ((value & 0x00ff0000) >>> 16) / 255; + color.g = ((value & 0x0000ff00) >>> 8) / 255; + color.b = ((value & 0x000000ff)) / 255; + }; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; + }()); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { + } + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); + }; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); + }; + MathUtils.signum = function (value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + }; + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + }; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + }; + MathUtils.randomTriangular = function (min, max) { + return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + }; + MathUtils.randomTriangularWith = function (min, max, mode) { + var u = Math.random(); + var d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + }; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; + }()); + spine.MathUtils = MathUtils; + var Interpolation = (function () { + function Interpolation() { + } + Interpolation.prototype.apply = function (start, end, a) { + return start + (end - start) * this.applyInternal(a); + }; + return Interpolation; + }()); + spine.Interpolation = Interpolation; + var Pow = (function (_super) { + __extends(Pow, _super); + function Pow(power) { + var _this = _super.call(this) || this; + _this.power = 2; + _this.power = power; + return _this; + } + Pow.prototype.applyInternal = function (a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + }; + return Pow; + }(Interpolation)); + spine.Pow = Pow; + var PowOut = (function (_super) { + __extends(PowOut, _super); + function PowOut(power) { + return _super.call(this, power) || this; + } + PowOut.prototype.applyInternal = function (a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + }; + return PowOut; + }(Pow)); + spine.PowOut = PowOut; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; + } + return array; + }; + Utils.ensureArrayCapacity = function (array, size, value) { + if (value === void 0) { value = 0; } + if (array.length >= size) + return array; + return Utils.setArraySize(array, size, value); + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.newShortArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Int16Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.toSinglePrecision = function (value) { + return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + }; + Utils.webkit602BugfixHelper = function (alpha, blend) { + }; + Utils.contains = function (array, element, identity) { + if (identity === void 0) { identity = true; } + for (var i = 0; i < array.length; i++) { + if (array[i] == element) + return true; + } + return false; + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; + }()); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { + } + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + }; + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + }; + Pool.prototype.free = function (item) { + if (item.reset) + item.reset(); + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) { + this.free(items[i]); + } + }; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; + }()); + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; + } + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; + }()); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; + } + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + }; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; + var WindowedMean = (function () { + function WindowedMean(windowSize) { + if (windowSize === void 0) { windowSize = 32; } + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + WindowedMean.prototype.hasEnoughData = function () { + return this.addedValues >= this.values.length; + }; + WindowedMean.prototype.addValue = function (value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + }; + WindowedMean.prototype.getMean = function () { + if (this.hasEnoughData()) { + if (this.dirty) { + var mean = 0; + for (var i = 0; i < this.values.length; i++) { + mean += this.values[i]; + } + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + else { + return 0; + } + }; + return WindowedMean; + }()); + spine.WindowedMean = WindowedMean; +})(spine || (spine = {})); +(function () { + if (!Math.fround) { + Math.fround = (function (array) { + return function (x) { + return array[0] = x, array[0]; + }; + })(new Float32Array(1)); + } +})(); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + var _this = _super.call(this, name) || this; + _this.id = (VertexAttachment.nextID++ & 65535) << 11; + _this.worldVerticesLength = 0; + _this.deformAttachment = _this; + return _this; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + var skeleton = slot.bone.skeleton; + var deformArray = slot.deform; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.copyTo = function (attachment) { + if (this.bones != null) { + attachment.bones = new Array(this.bones.length); + spine.Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } + else + attachment.bones = null; + if (this.vertices != null) { + attachment.vertices = spine.Utils.newFloatArray(this.vertices.length); + spine.Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + else + attachment.vertices = null; + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.deformAttachment = this.deformAttachment; + }; + VertexAttachment.nextID = 0; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AttachmentType; + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + AttachmentType[AttachmentType["Point"] = 5] = "Point"; + AttachmentType[AttachmentType["Clipping"] = 6] = "Clipping"; + })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + BoundingBoxAttachment.prototype.copy = function () { + var copy = new BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + }; + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var ClippingAttachment = (function (_super) { + __extends(ClippingAttachment, _super); + function ClippingAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1); + return _this; + } + ClippingAttachment.prototype.copy = function () { + var copy = new ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + }; + return ClippingAttachment; + }(spine.VertexAttachment)); + spine.ClippingAttachment = ClippingAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + _this.tempColor = new spine.Color(0, 0, 0, 0); + return _this; + } + MeshAttachment.prototype.updateUVs = function () { + var regionUVs = this.regionUVs; + if (this.uvs == null || this.uvs.length != regionUVs.length) + this.uvs = spine.Utils.newFloatArray(regionUVs.length); + var uvs = this.uvs; + var n = this.uvs.length; + var u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof spine.TextureAtlasRegion) { + var region = this.region; + var textureWidth = region.texture.getImage().width, textureHeight = region.texture.getImage().height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (var i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (var i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (var i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } + else if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (var i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + }; + MeshAttachment.prototype.copy = function () { + if (this.parentMesh != null) + return this.newLinkedMesh(); + var copy = new MeshAttachment(this.name); + copy.region = this.region; + copy.path = this.path; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + spine.Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = new Array(this.uvs.length); + spine.Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + spine.Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + if (this.edges != null) { + copy.edges = new Array(this.edges.length); + spine.Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + }; + MeshAttachment.prototype.newLinkedMesh = function () { + var copy = new MeshAttachment(this.name); + copy.region = this.region; + copy.path = this.path; + copy.color.setFromColor(this.color); + copy.deformAttachment = this.deformAttachment; + copy.setParentMesh(this.parentMesh != null ? this.parentMesh : this); + copy.updateUVs(); + return copy; + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + var _this = _super.call(this, name) || this; + _this.closed = false; + _this.constantSpeed = false; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + PathAttachment.prototype.copy = function () { + var copy = new PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + spine.Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + }; + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PointAttachment = (function (_super) { + __extends(PointAttachment, _super); + function PointAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.38, 0.94, 0, 1); + return _this; + } + PointAttachment.prototype.computeWorldPosition = function (bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + }; + PointAttachment.prototype.computeWorldRotation = function (bone) { + var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation); + var x = cos * bone.a + sin * bone.b; + var y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * spine.MathUtils.radDeg; + }; + PointAttachment.prototype.copy = function () { + var copy = new PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + }; + return PointAttachment; + }(spine.VertexAttachment)); + spine.PointAttachment = PointAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + var _this = _super.call(this, name) || this; + _this.x = 0; + _this.y = 0; + _this.scaleX = 1; + _this.scaleY = 1; + _this.rotation = 0; + _this.width = 0; + _this.height = 0; + _this.color = new spine.Color(1, 1, 1, 1); + _this.offset = spine.Utils.newFloatArray(8); + _this.uvs = spine.Utils.newFloatArray(8); + _this.tempColor = new spine.Color(1, 1, 1, 1); + return _this; + } + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.setRegion = function (region) { + this.region = region; + var uvs = this.uvs; + if (region.rotate) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; + } + else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + }; + RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) { + var vertexOffset = this.offset; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = vertexOffset[RegionAttachment.OX1]; + offsetY = vertexOffset[RegionAttachment.OY1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX2]; + offsetY = vertexOffset[RegionAttachment.OY2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX3]; + offsetY = vertexOffset[RegionAttachment.OY3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX4]; + offsetY = vertexOffset[RegionAttachment.OY4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + }; + RegionAttachment.prototype.copy = function () { + var copy = new RegionAttachment(this.name); + copy.region = this.region; + copy.rendererObject = this.rendererObject; + copy.path = this.path; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + spine.Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + spine.Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + return copy; + }; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var JitterEffect = (function () { + function JitterEffect(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; + } + JitterEffect.prototype.begin = function (skeleton) { + }; + JitterEffect.prototype.transform = function (position, uv, light, dark) { + position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + }; + JitterEffect.prototype.end = function () { + }; + return JitterEffect; + }()); + spine.JitterEffect = JitterEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SwirlEffect = (function () { + function SwirlEffect(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; + } + SwirlEffect.prototype.begin = function (skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + }; + SwirlEffect.prototype.transform = function (position, uv, light, dark) { + var radAngle = this.angle * spine.MathUtils.degreesToRadians; + var x = position.x - this.worldX; + var y = position.y - this.worldY; + var dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + var cos = Math.cos(theta); + var sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + }; + SwirlEffect.prototype.end = function () { + }; + SwirlEffect.interpolation = new spine.PowOut(2); + return SwirlEffect; + }()); + spine.SwirlEffect = SwirlEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + return _super.call(this, function (image) { return new spine.canvas.CanvasTexture(image); }, pathPrefix) || this; + } + return AssetManager; + }(spine.AssetManager)); + canvas.AssetManager = AssetManager; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var CanvasTexture = (function (_super) { + __extends(CanvasTexture, _super); + function CanvasTexture(image) { + return _super.call(this, image) || this; + } + CanvasTexture.prototype.setFilters = function (minFilter, magFilter) { }; + CanvasTexture.prototype.setWraps = function (uWrap, vWrap) { }; + CanvasTexture.prototype.dispose = function () { }; + return CanvasTexture; + }(spine.Texture)); + canvas.CanvasTexture = CanvasTexture; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var canvas; + (function (canvas) { + var SkeletonRenderer = (function () { + function SkeletonRenderer(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.vertices = spine.Utils.newFloatArray(8 * 1024); + this.tempColor = new spine.Color(); + this.ctx = context; + } + SkeletonRenderer.prototype.draw = function (skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + }; + SkeletonRenderer.prototype.drawImages = function (skeleton) { + var ctx = this.ctx; + var drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + ctx.save(); + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + if (!slot.bone.active) + continue; + var attachment = slot.getAttachment(); + var regionAttachment = null; + var region = null; + var image = null; + if (attachment instanceof spine.RegionAttachment) { + regionAttachment = attachment; + region = regionAttachment.region; + image = region.texture.getImage(); + } + else + continue; + var skeleton_1 = slot.bone.skeleton; + var skeletonColor = skeleton_1.color; + var slotColor = slot.color; + var regionColor = regionAttachment.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, alpha); + var att = attachment; + var bone = slot.bone; + var w = region.width; + var h = region.height; + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + var atlasScale = att.width / w; + ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); + ctx.translate(w / 2, h / 2); + if (attachment.region.rotate) { + var t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + ctx.restore(); + }; + SkeletonRenderer.prototype.drawTriangles = function (skeleton) { + var blendMode = null; + var vertices = this.vertices; + var triangles = null; + var drawOrder = skeleton.drawOrder; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var slot = drawOrder[i]; + var attachment = slot.getAttachment(); + var texture = null; + var region = null; + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.texture.getImage(); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture.getImage(); + } + else + continue; + if (texture != null) { + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + } + var skeleton_2 = slot.bone.skeleton; + var skeletonColor = skeleton_2.color; + var slotColor = slot.color; + var attachmentColor = attachment.color; + var alpha = skeletonColor.a * slotColor.a * attachmentColor.a; + var color = this.tempColor; + color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha); + var ctx = this.ctx; + ctx.globalAlpha = color.a; + for (var j = 0; j < triangles.length; j += 3) { + var t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + var x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + var x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + var 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + }; + SkeletonRenderer.prototype.drawTriangle = function (img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + var ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + }; + SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = region.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var vertices = this.vertices; + var uvs = region.uvs; + vertices[spine.RegionAttachment.C1R] = color.r; + vertices[spine.RegionAttachment.C1G] = color.g; + vertices[spine.RegionAttachment.C1B] = color.b; + vertices[spine.RegionAttachment.C1A] = color.a; + vertices[spine.RegionAttachment.U1] = uvs[0]; + vertices[spine.RegionAttachment.V1] = uvs[1]; + vertices[spine.RegionAttachment.C2R] = color.r; + vertices[spine.RegionAttachment.C2G] = color.g; + vertices[spine.RegionAttachment.C2B] = color.b; + vertices[spine.RegionAttachment.C2A] = color.a; + vertices[spine.RegionAttachment.U2] = uvs[2]; + vertices[spine.RegionAttachment.V2] = uvs[3]; + vertices[spine.RegionAttachment.C3R] = color.r; + vertices[spine.RegionAttachment.C3G] = color.g; + vertices[spine.RegionAttachment.C3B] = color.b; + vertices[spine.RegionAttachment.C3A] = color.a; + vertices[spine.RegionAttachment.U3] = uvs[4]; + vertices[spine.RegionAttachment.V3] = uvs[5]; + vertices[spine.RegionAttachment.C4R] = color.r; + vertices[spine.RegionAttachment.C4G] = color.g; + vertices[spine.RegionAttachment.C4B] = color.b; + vertices[spine.RegionAttachment.C4A] = color.a; + vertices[spine.RegionAttachment.U4] = uvs[6]; + vertices[spine.RegionAttachment.V4] = uvs[7]; + return vertices; + }; + SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) { + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = mesh.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = pma ? alpha : 1; + var 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); + var numVertices = mesh.worldVerticesLength / 2; + if (this.vertices.length < mesh.worldVerticesLength) { + this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength); + } + var vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE); + var uvs = mesh.uvs; + for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4; + return SkeletonRenderer; + }()); + canvas.SkeletonRenderer = SkeletonRenderer; + })(canvas = spine.canvas || (spine.canvas = {})); +})(spine || (spine = {})); +//# sourceMappingURL=spine-canvas.js.map \ No newline at end of file diff --git a/release/MAC版本/lib/4.0/spine-canvas.js b/release/MAC版本/lib/4.0/spine-canvas.js new file mode 100644 index 0000000..a62bb5f --- /dev/null +++ b/release/MAC版本/lib/4.0/spine-canvas.js @@ -0,0 +1,9066 @@ +var spine = (() => { + var __defProp = Object.defineProperty; + var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); + var __export = (target, all) => { + __markAsModule(target); + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // spine-canvas/src/index.ts + var src_exports = {}; + __export(src_exports, { + AlphaTimeline: () => AlphaTimeline, + Animation: () => Animation, + AnimationState: () => AnimationState, + AnimationStateAdapter: () => AnimationStateAdapter, + AnimationStateData: () => AnimationStateData, + AssetManager: () => AssetManager, + AssetManagerBase: () => AssetManagerBase, + AtlasAttachmentLoader: () => AtlasAttachmentLoader, + Attachment: () => Attachment, + AttachmentTimeline: () => AttachmentTimeline, + BinaryInput: () => BinaryInput, + BlendMode: () => BlendMode, + Bone: () => Bone, + BoneData: () => BoneData, + BoundingBoxAttachment: () => BoundingBoxAttachment, + CURRENT: () => CURRENT, + CanvasTexture: () => CanvasTexture, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + ConstraintData: () => ConstraintData, + CurveTimeline: () => CurveTimeline, + CurveTimeline1: () => CurveTimeline1, + CurveTimeline2: () => CurveTimeline2, + DebugUtils: () => DebugUtils, + DeformTimeline: () => DeformTimeline, + Downloader: () => Downloader, + DrawOrderTimeline: () => DrawOrderTimeline, + Event: () => Event, + EventData: () => EventData, + EventQueue: () => EventQueue, + EventTimeline: () => EventTimeline, + EventType: () => EventType, + FIRST: () => FIRST, + FakeTexture: () => FakeTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + JitterEffect: () => JitterEffect, + MathUtils: () => MathUtils, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + PointAttachment: () => PointAttachment, + Pool: () => Pool, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + StringSet: () => StringSet, + SwirlEffect: () => SwirlEffect, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TransformMode: () => TransformMode, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + VertexAttachment: () => VertexAttachment, + WindowedMean: () => WindowedMean + }); + + // spine-core/src/Utils.ts + var IntSet = class { + constructor() { + this.array = new Array(); + } + add(value) { + let contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] != void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } + }; + var StringSet = class { + constructor() { + this.entries = {}; + this.size = 0; + } + add(value) { + let contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + let oldSize = this.size; + for (var i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize != this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } + }; + var _Color = class { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) == "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + static fromString(hex) { + return new _Color().setFromString(hex); + } + }; + var Color = _Color; + Color.WHITE = new _Color(1, 1, 1, 1); + Color.RED = new _Color(1, 0, 0, 1); + Color.GREEN = new _Color(0, 1, 0, 1); + Color.BLUE = new _Color(0, 0, 1, 1); + Color.MAGENTA = new _Color(1, 0, 1, 1); + var _MathUtils = class { + static clamp(value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + let u = Math.random(); + let d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } + }; + var MathUtils = _MathUtils; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = _MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / _MathUtils.PI; + MathUtils.radDeg = _MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = _MathUtils.PI / 180; + MathUtils.degRad = _MathUtils.degreesToRadians; + var Interpolation = class { + apply(start, end, a) { + return start + (end - start) * this.applyInternal(a); + } + }; + var Pow = class extends Interpolation { + constructor(power) { + super(); + this.power = 2; + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + } + }; + var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + } + }; + var _Utils = class { + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + static setArraySize(array, size, value = 0) { + let oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) + array[i] = value; + } + return array; + } + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) + return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + let array = new Array(size); + for (let i = 0; i < size; i++) + array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + static webkit602BugfixHelper(alpha, blend) { + } + static contains(array, element, identity = true) { + for (var i = 0; i < array.length; i++) + if (array[i] == element) + return true; + return false; + } + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } + }; + var Utils = _Utils; + Utils.SUPPORTS_TYPED_ARRAYS = typeof Float32Array !== "undefined"; + var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + let bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + } + }; + var Pool = class { + constructor(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + if (item.reset) + item.reset(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } + }; + var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + let x = this.x; + let y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + let len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + } + }; + var TimeKeeper = class { + constructor() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1e3; + this.frameCount = 0; + this.frameTime = 0; + } + update() { + let now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } + }; + var WindowedMean = class { + constructor(windowSize = 32) { + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } + }; + + // spine-core/src/attachments/Attachment.ts + var Attachment = class { + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + }; + var _VertexAttachment = class extends Attachment { + constructor(name) { + super(name); + this.id = _VertexAttachment.nextID++; + this.bones = null; + this.vertices = null; + this.worldVerticesLength = 0; + this.deformAttachment = this; + } + computeWorldVertices(slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + let skeleton = slot.bone.skeleton; + let deformArray = slot.deform; + let vertices = this.vertices; + let bones = this.bones; + if (!bones) { + if (deformArray.length > 0) + vertices = deformArray; + let bone = slot.bone; + let x = bone.worldX; + let y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + let vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + let n = bones[v]; + v += n + 1; + skip += n; + } + let skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } else { + let deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + } + copyTo(attachment) { + if (this.bones) { + attachment.bones = new Array(this.bones.length); + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } else + attachment.vertices = null; + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.deformAttachment = this.deformAttachment; + } + }; + var VertexAttachment = _VertexAttachment; + VertexAttachment.nextID = 0; + + // spine-core/src/Animation.ts + var Animation = class { + constructor(name, timelines, duration) { + this.timelines = null; + this.timelineIds = null; + if (!name) + throw new Error("name cannot be null."); + this.name = name; + this.setTimelines(timelines); + this.duration = duration; + } + setTimelines(timelines) { + if (!timelines) + throw new Error("timelines cannot be null."); + this.timelines = timelines; + this.timelineIds = new StringSet(); + for (var i = 0; i < timelines.length; i++) + this.timelineIds.addAll(timelines[i].getPropertyIds()); + } + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) + return true; + return false; + } + apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + let timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + } + }; + var MixBlend; + (function(MixBlend2) { + MixBlend2[MixBlend2["setup"] = 0] = "setup"; + MixBlend2[MixBlend2["first"] = 1] = "first"; + MixBlend2[MixBlend2["replace"] = 2] = "replace"; + MixBlend2[MixBlend2["add"] = 3] = "add"; + })(MixBlend || (MixBlend = {})); + var MixDirection; + (function(MixDirection2) { + MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn"; + MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut"; + })(MixDirection || (MixDirection = {})); + var Property = { + rotate: 0, + x: 1, + y: 2, + scaleX: 3, + scaleY: 4, + shearX: 5, + shearY: 6, + rgb: 7, + alpha: 8, + rgb2: 9, + attachment: 10, + deform: 11, + event: 12, + drawOrder: 13, + ikConstraint: 14, + transformConstraint: 15, + pathConstraintPosition: 16, + pathConstraintSpacing: 17, + pathConstraintMix: 18 + }; + var Timeline = class { + constructor(frameCount, propertyIds) { + this.propertyIds = null; + this.frames = null; + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + getFrameEntries() { + return 1; + } + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + static search1(frames, time) { + let n = frames.length; + for (let i = 1; i < n; i++) + if (frames[i] > time) + return i - 1; + return n - 1; + } + static search(frames, time, step) { + let n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) + return i - step; + return n - step; + } + }; + var CurveTimeline = class extends Timeline { + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + this.curves = null; + this.curves = Utils.newFloatArray(frameCount + bezierCount * 18); + this.curves[frameCount - 1] = 1; + } + setLinear(frame) { + this.curves[frame] = 0; + } + setStepped(frame) { + this.curves[frame] = 1; + } + shrink(bezierCount) { + let size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + let newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getBezierValue(time, frameIndex, valueOffset, i) { + let curves = this.curves; + if (curves[i] > time) { + let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + let x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } + }; + var CurveTimeline1 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, [propertyId]); + } + getFrameEntries() { + return 2; + } + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[frame + 1] = value; + } + getCurveValue(time) { + let frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + let curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: + let before = frames[i], value = frames[i + 1]; + return value + (time - before) / (frames[i + 2] - before) * (frames[i + 2 + 1] - value); + case 1: + return frames[i + 1]; + } + return this.getBezierValue(time, i, 1, curveType - 2); + } + }; + var CurveTimeline2 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId1, propertyId2) { + super(frameCount, bezierCount, [propertyId1, propertyId2]); + } + getFrameEntries() { + return 3; + } + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[frame + 1] = value1; + this.frames[frame + 2] = value2; + } + }; + var RotateTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.rotate + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.rotation = bone.data.rotation; + return; + case 1: + bone.rotation += (bone.data.rotation - bone.rotation) * alpha; + } + return; + } + let r = this.getCurveValue(time); + switch (blend) { + case 0: + bone.rotation = bone.data.rotation + r * alpha; + break; + case 1: + case 2: + r += bone.data.rotation - bone.rotation; + case 3: + bone.rotation += r * alpha; + } + } + }; + var TranslateTimeline = class extends CurveTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex, Property.y + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case 1: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search(frames, time, 3); + let curveType = this.curves[i / 3]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[i + 1]; + y = frames[i + 2]; + let t = (time - before) / (frames[i + 3] - before); + x += (frames[i + 3 + 1] - x) * t; + y += (frames[i + 3 + 2] - y) * t; + break; + case 1: + x = frames[i + 1]; + y = frames[i + 2]; + break; + default: + x = this.getBezierValue(time, i, 1, curveType - 2); + y = this.getBezierValue(time, i, 2, curveType + 18 - 2); + } + switch (blend) { + case 0: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case 1: + case 2: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3: + bone.x += x * alpha; + bone.y += y * alpha; + } + } + }; + var TranslateXTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.x = bone.data.x; + return; + case 1: + bone.x += (bone.data.x - bone.x) * alpha; + } + return; + } + let x = this.getCurveValue(time); + switch (blend) { + case 0: + bone.x = bone.data.x + x * alpha; + break; + case 1: + case 2: + bone.x += (bone.data.x + x - bone.x) * alpha; + break; + case 3: + bone.x += x * alpha; + } + } + }; + var TranslateYTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.y + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.y = bone.data.y; + return; + case 1: + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let y = this.getCurveValue(time); + switch (blend) { + case 0: + bone.y = bone.data.y + y * alpha; + break; + case 1: + case 2: + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3: + bone.y += y * alpha; + } + } + }; + var ScaleTimeline = class extends CurveTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex, Property.scaleY + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case 1: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let x, y; + let i = Timeline.search(frames, time, 3); + let curveType = this.curves[i / 3]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[i + 1]; + y = frames[i + 2]; + let t = (time - before) / (frames[i + 3] - before); + x += (frames[i + 3 + 1] - x) * t; + y += (frames[i + 3 + 2] - y) * t; + break; + case 1: + x = frames[i + 1]; + y = frames[i + 2]; + break; + default: + x = this.getBezierValue(time, i, 1, curveType - 2); + y = this.getBezierValue(time, i, 2, curveType + 18 - 2); + } + x *= bone.data.scaleX; + y *= bone.data.scaleY; + if (alpha == 1) { + if (blend == 3) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } else { + bone.scaleX = x; + bone.scaleY = y; + } + } else { + let bx = 0, by = 0; + if (direction == 1) { + switch (blend) { + case 0: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1: + case 2: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 1: + case 2: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 3: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ScaleXTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.scaleX = bone.data.scaleX; + return; + case 1: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + } + return; + } + let x = this.getCurveValue(time) * bone.data.scaleX; + if (alpha == 1) { + if (blend == 3) + bone.scaleX += x - bone.data.scaleX; + else + bone.scaleX = x; + } else { + let bx = 0; + if (direction == 1) { + switch (blend) { + case 0: + bx = bone.data.scaleX; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + break; + case 1: + case 2: + bx = bone.scaleX; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + break; + case 3: + bone.scaleX += (x - bone.data.scaleX) * alpha; + } + } else { + switch (blend) { + case 0: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + bone.scaleX = bx + (x - bx) * alpha; + break; + case 1: + case 2: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + bone.scaleX = bx + (x - bx) * alpha; + break; + case 3: + bone.scaleX += (x - bone.data.scaleX) * alpha; + } + } + } + } + }; + var ScaleYTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.scaleY = bone.data.scaleY; + return; + case 1: + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let y = this.getCurveValue(time) * bone.data.scaleY; + if (alpha == 1) { + if (blend == 3) + bone.scaleY += y - bone.data.scaleY; + else + bone.scaleY = y; + } else { + let by = 0; + if (direction == 1) { + switch (blend) { + case 0: + by = bone.data.scaleY; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1: + case 2: + by = bone.scaleY; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3: + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0: + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleY = by + (y - by) * alpha; + break; + case 1: + case 2: + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleY = by + (y - by) * alpha; + break; + case 3: + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ShearTimeline = class extends CurveTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex, Property.shearY + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case 1: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search(frames, time, 3); + let curveType = this.curves[i / 3]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[i + 1]; + y = frames[i + 2]; + let t = (time - before) / (frames[i + 3] - before); + x += (frames[i + 3 + 1] - x) * t; + y += (frames[i + 3 + 2] - y) * t; + break; + case 1: + x = frames[i + 1]; + y = frames[i + 2]; + break; + default: + x = this.getBezierValue(time, i, 1, curveType - 2); + y = this.getBezierValue(time, i, 2, curveType + 18 - 2); + } + switch (blend) { + case 0: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1: + case 2: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + } + }; + var ShearXTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.shearX = bone.data.shearX; + return; + case 1: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + } + return; + } + let x = this.getCurveValue(time); + switch (blend) { + case 0: + bone.shearX = bone.data.shearX + x * alpha; + break; + case 1: + case 2: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + break; + case 3: + bone.shearX += x * alpha; + } + } + }; + var ShearYTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearY + "|" + boneIndex); + this.boneIndex = 0; + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + bone.shearY = bone.data.shearY; + return; + case 1: + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let y = this.getCurveValue(time); + switch (blend) { + case 0: + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1: + case 2: + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3: + bone.shearY += y * alpha; + } + } + }; + var RGBATimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex + ]); + this.slotIndex = 0; + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 5; + } + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[frame + 1] = r; + this.frames[frame + 2] = g; + this.frames[frame + 3] = b; + this.frames[frame + 4] = a; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0: + color.setFromColor(setup); + return; + case 1: + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + let i = Timeline.search(frames, time, 5); + let curveType = this.curves[i / 5]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + a = frames[i + 4]; + let t = (time - before) / (frames[i + 5] - before); + r += (frames[i + 5 + 1] - r) * t; + g += (frames[i + 5 + 2] - g) * t; + b += (frames[i + 5 + 3] - b) * t; + a += (frames[i + 5 + 4] - a) * t; + break; + case 1: + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + a = frames[i + 4]; + break; + default: + r = this.getBezierValue(time, i, 1, curveType - 2); + g = this.getBezierValue(time, i, 2, curveType + 18 - 2); + b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2); + } + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == 0) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } + }; + var RGBTimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex + ]); + this.slotIndex = 0; + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[frame + 1] = r; + this.frames[frame + 2] = g; + this.frames[frame + 3] = b; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + return; + case 1: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0; + let i = Timeline.search(frames, time, 4); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + let t = (time - before) / (frames[i + 4] - before); + r += (frames[i + 4 + 1] - r) * t; + g += (frames[i + 4 + 2] - g) * t; + b += (frames[i + 4 + 3] - b) * t; + break; + case 1: + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + break; + default: + r = this.getBezierValue(time, i, 1, curveType - 2); + g = this.getBezierValue(time, i, 2, curveType + 18 - 2); + b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + } + if (alpha == 1) { + color.r = r; + color.g = g; + color.b = b; + } else { + if (blend == 0) { + let setup = slot.data.color; + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + } + color.r += (r - color.r) * alpha; + color.g += (g - color.g) * alpha; + color.b += (b - color.b) * alpha; + } + } + }; + var AlphaTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + this.slotIndex = 0; + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let color = slot.color; + if (time < this.frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0: + color.a = setup.a; + return; + case 1: + color.a += (setup.a - color.a) * alpha; + } + return; + } + let a = this.getCurveValue(time); + if (alpha == 1) + color.a = a; + else { + if (blend == 0) + color.a = slot.data.color.a; + color.a += (a - color.a) * alpha; + } + } + }; + var RGBA2Timeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = 0; + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 8; + } + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[frame + 1] = r; + this.frames[frame + 2] = g; + this.frames[frame + 3] = b; + this.frames[frame + 4] = a; + this.frames[frame + 5] = r2; + this.frames[frame + 6] = g2; + this.frames[frame + 7] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0: + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1: + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search(frames, time, 8); + let curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + a = frames[i + 4]; + r2 = frames[i + 5]; + g2 = frames[i + 6]; + b2 = frames[i + 7]; + let t = (time - before) / (frames[i + 8] - before); + r += (frames[i + 8 + 1] - r) * t; + g += (frames[i + 8 + 2] - g) * t; + b += (frames[i + 8 + 3] - b) * t; + a += (frames[i + 8 + 4] - a) * t; + r2 += (frames[i + 8 + 5] - r2) * t; + g2 += (frames[i + 8 + 6] - g2) * t; + b2 += (frames[i + 8 + 7] - b2) * t; + break; + case 1: + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + a = frames[i + 4]; + r2 = frames[i + 5]; + g2 = frames[i + 6]; + b2 = frames[i + 7]; + break; + default: + r = this.getBezierValue(time, i, 1, curveType - 2); + g = this.getBezierValue(time, i, 2, curveType + 18 - 2); + b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2); + r2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2); + g2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2); + b2 = this.getBezierValue(time, i, 7, curveType + 18 * 6 - 2); + } + if (alpha == 1) { + light.set(r, g, b, a); + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0) { + light.setFromColor(slot.data.color); + let setupDark = slot.data.darkColor; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var RGB2Timeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = 0; + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 7; + } + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[frame + 1] = r; + this.frames[frame + 2] = g; + this.frames[frame + 3] = b; + this.frames[frame + 4] = r2; + this.frames[frame + 5] = g2; + this.frames[frame + 6] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search(frames, time, 7); + let curveType = this.curves[i / 7]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + r2 = frames[i + 4]; + g2 = frames[i + 5]; + b2 = frames[i + 6]; + let t = (time - before) / (frames[i + 7] - before); + r += (frames[i + 7 + 1] - r) * t; + g += (frames[i + 7 + 2] - g) * t; + b += (frames[i + 7 + 3] - b) * t; + r2 += (frames[i + 7 + 4] - r2) * t; + g2 += (frames[i + 7 + 5] - g2) * t; + b2 += (frames[i + 7 + 6] - b2) * t; + break; + case 1: + r = frames[i + 1]; + g = frames[i + 2]; + b = frames[i + 3]; + r2 = frames[i + 4]; + g2 = frames[i + 5]; + b2 = frames[i + 6]; + break; + default: + r = this.getBezierValue(time, i, 1, curveType - 2); + g = this.getBezierValue(time, i, 2, curveType + 18 - 2); + b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + r2 = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2); + g2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2); + b2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2); + } + if (alpha == 1) { + light.r = r; + light.g = g; + light.b = b; + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.r += (r - light.r) * alpha; + light.g += (g - light.g) * alpha; + light.b += (b - light.b) * alpha; + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var AttachmentTimeline = class extends Timeline { + constructor(frameCount, slotIndex) { + super(frameCount, [ + Property.attachment + "|" + slotIndex + ]); + this.slotIndex = 0; + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + if (direction == 1) { + if (blend == 0) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + if (time < this.frames[0]) { + if (blend == 0 || blend == 1) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]); + } + setAttachment(skeleton, slot, attachmentName) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } + }; + var DeformTimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, [ + Property.deform + "|" + slotIndex + "|" + attachment.id + ]); + this.slotIndex = 0; + this.attachment = null; + this.vertices = null; + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + let curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: + let x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + let x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + let x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.deformAttachment != this.attachment) + return; + let deform = slot.deform; + if (deform.length == 0) + blend = 0; + let vertices = this.vertices; + let vertexCount = vertices[0].length; + let frames = this.frames; + if (time < frames[0]) { + let vertexAttachment = slotAttachment; + switch (blend) { + case 0: + deform.length = 0; + return; + case 1: + if (alpha == 1) { + deform.length = 0; + return; + } + deform.length = vertexCount; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + return; + } + deform.length = vertexCount; + if (time >= frames[frames.length - 1]) { + let lastVertices = vertices[frames.length - 1]; + if (alpha == 1) { + if (blend == 3) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] - setupVertices[i2]; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2]; + } + } else + Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } else { + switch (blend) { + case 0: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let setup = setupVertices[i2]; + deform[i2] = setup + (lastVertices[i2] - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] = lastVertices[i2] * alpha; + } + break; + } + case 1: + case 2: + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - deform[i2]) * alpha; + break; + case 3: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] * alpha; + } + } + } + return; + } + let frame = Timeline.search1(frames, time); + let percent = this.getCurvePercent(time, frame); + let prevVertices = vertices[frame]; + let nextVertices = vertices[frame + 1]; + if (alpha == 1) { + if (blend == 3) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + switch (blend) { + case 0: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2], setup = setupVertices[i2]; + deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + break; + } + case 1: + case 2: + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha; + } + break; + case 3: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + } + } + } + }; + var _EventTimeline = class extends Timeline { + constructor(frameCount) { + super(frameCount, _EventTimeline.propertyIds); + this.events = null; + this.events = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (!firedEvents) + return; + let frames = this.frames; + let frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search1(frames, lastTime) + 1; + let frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] != frameTime) + break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } + }; + var EventTimeline = _EventTimeline; + EventTimeline.propertyIds = ["" + Property.event]; + var _DrawOrderTimeline = class extends Timeline { + constructor(frameCount) { + super(frameCount, _DrawOrderTimeline.propertyIds); + this.drawOrders = null; + this.drawOrders = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (direction == 1) { + if (blend == 0) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + if (time < this.frames[0]) { + if (blend == 0 || blend == 1) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + let drawOrderToSetupIndex = this.drawOrders[Timeline.search1(this.frames, time)]; + if (!drawOrderToSetupIndex) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + else { + let drawOrder = skeleton.drawOrder; + let slots = skeleton.slots; + for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } + }; + var DrawOrderTimeline = _DrawOrderTimeline; + DrawOrderTimeline.propertyIds = ["" + Property.drawOrder]; + var IkConstraintTimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, ikConstraintIndex) { + super(frameCount, bezierCount, [ + Property.ikConstraint + "|" + ikConstraintIndex + ]); + this.ikConstraintIndex = 0; + this.ikConstraintIndex = ikConstraintIndex; + } + getFrameEntries() { + return 6; + } + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[frame + 1] = mix; + this.frames[frame + 2] = softness; + this.frames[frame + 3] = bendDirection; + this.frames[frame + 4] = compress ? 1 : 0; + this.frames[frame + 5] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case 1: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + let mix = 0, softness = 0; + let i = Timeline.search(frames, time, 6); + let curveType = this.curves[i / 6]; + switch (curveType) { + case 0: + let before = frames[i]; + mix = frames[i + 1]; + softness = frames[i + 2]; + let t = (time - before) / (frames[i + 6] - before); + mix += (frames[i + 6 + 1] - mix) * t; + softness += (frames[i + 6 + 2] - softness) * t; + break; + case 1: + mix = frames[i + 1]; + softness = frames[i + 2]; + break; + default: + mix = this.getBezierValue(time, i, 1, curveType - 2); + softness = this.getBezierValue(time, i, 2, curveType + 18 - 2); + } + if (blend == 0) { + constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (direction == 1) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = frames[i + 3]; + constraint.compress = frames[i + 4] != 0; + constraint.stretch = frames[i + 5] != 0; + } + } else { + constraint.mix += (mix - constraint.mix) * alpha; + constraint.softness += (softness - constraint.softness) * alpha; + if (direction == 0) { + constraint.bendDirection = frames[i + 3]; + constraint.compress = frames[i + 4] != 0; + constraint.stretch = frames[i + 5] != 0; + } + } + } + }; + var TransformConstraintTimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, transformConstraintIndex) { + super(frameCount, bezierCount, [ + Property.transformConstraint + "|" + transformConstraintIndex + ]); + this.transformConstraintIndex = 0; + this.transformConstraintIndex = transformConstraintIndex; + } + getFrameEntries() { + return 7; + } + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + let frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[frame + 1] = mixRotate; + frames[frame + 2] = mixX; + frames[frame + 3] = mixY; + frames[frame + 4] = mixScaleX; + frames[frame + 5] = mixScaleY; + frames[frame + 6] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + let data = constraint.data; + switch (blend) { + case 0: + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + return; + case 1: + constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (data.mixX - constraint.mixX) * alpha; + constraint.mixY += (data.mixY - constraint.mixY) * alpha; + constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + let i = Timeline.search(frames, time, 7); + let curveType = this.curves[i / 7]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[i + 1]; + x = frames[i + 2]; + y = frames[i + 3]; + scaleX = frames[i + 4]; + scaleY = frames[i + 5]; + shearY = frames[i + 6]; + let t = (time - before) / (frames[i + 7] - before); + rotate += (frames[i + 7 + 1] - rotate) * t; + x += (frames[i + 7 + 2] - x) * t; + y += (frames[i + 7 + 3] - y) * t; + scaleX += (frames[i + 7 + 4] - scaleX) * t; + scaleY += (frames[i + 7 + 5] - scaleY) * t; + shearY += (frames[i + 7 + 6] - shearY) * t; + break; + case 1: + rotate = frames[i + 1]; + x = frames[i + 2]; + y = frames[i + 3]; + scaleX = frames[i + 4]; + scaleY = frames[i + 5]; + shearY = frames[i + 6]; + break; + default: + rotate = this.getBezierValue(time, i, 1, curveType - 2); + x = this.getBezierValue(time, i, 2, curveType + 18 - 2); + y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + scaleX = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2); + scaleY = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2); + shearY = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2); + } + if (blend == 0) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; + constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; + constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + } + } + }; + var PathConstraintPositionTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex); + this.pathConstraintIndex = 0; + this.pathConstraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + constraint.position = constraint.data.position; + return; + case 1: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } + return; + } + let position = this.getCurveValue(time); + if (blend == 0) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + } + }; + var PathConstraintSpacingTimeline = class extends CurveTimeline1 { + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex); + this.pathConstraintIndex = 0; + this.pathConstraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + constraint.spacing = constraint.data.spacing; + return; + case 1: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } + return; + } + let spacing = this.getCurveValue(time); + if (blend == 0) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + } + }; + var PathConstraintMixTimeline = class extends CurveTimeline { + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, [ + Property.pathConstraintMix + "|" + pathConstraintIndex + ]); + this.pathConstraintIndex = 0; + this.pathConstraintIndex = pathConstraintIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, mixRotate, mixX, mixY) { + let frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[frame + 1] = mixRotate; + frames[frame + 2] = mixX; + frames[frame + 3] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0: + constraint.mixRotate = constraint.data.mixRotate; + constraint.mixX = constraint.data.mixX; + constraint.mixY = constraint.data.mixY; + return; + case 1: + constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha; + constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha; + } + return; + } + let rotate, x, y; + let i = Timeline.search(frames, time, 4); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[i + 1]; + x = frames[i + 2]; + y = frames[i + 3]; + let t = (time - before) / (frames[i + 4] - before); + rotate += (frames[i + 4 + 1] - rotate) * t; + x += (frames[i + 4 + 2] - x) * t; + y += (frames[i + 4 + 3] - y) * t; + break; + case 1: + rotate = frames[i + 1]; + x = frames[i + 2]; + y = frames[i + 3]; + break; + default: + rotate = this.getBezierValue(time, i, 1, curveType - 2); + x = this.getBezierValue(time, i, 2, curveType + 18 - 2); + y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2); + } + if (blend == 0) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + } + } + }; + + // spine-core/src/AnimationState.ts + var AnimationState = class { + constructor(data) { + this.data = null; + this.tracks = new Array(); + this.timeScale = 1; + this.unkeyedState = 0; + this.events = new Array(); + this.listeners = new Array(); + this.queue = new EventQueue(this); + this.propertyIDs = new StringSet(); + this.animationsChanged = false; + this.trackEntryPool = new Pool(() => new TrackEntry()); + this.data = data; + } + static emptyAnimation() { + if (!_emptyAnimation) + _emptyAnimation = new Animation("", [], 0); + return _emptyAnimation; + } + update(delta) { + delta *= this.timeScale; + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let current = tracks[i]; + if (!current) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + let nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) + from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + updateMixingFrom(to, delta) { + let from = to.mixingFrom; + if (!from) + return true; + let finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + apply(skeleton) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + let events = this.events; + let tracks = this.tracks; + let applied = false; + for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) { + let current = tracks[i2]; + if (!current || current.delay > 0) + continue; + applied = true; + let blend = i2 == 0 ? MixBlend.first : current.mixBlend; + let mix = current.alpha; + if (current.mixingFrom) + mix *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && !current.next) + mix = 0; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + let timelines = current.animation.timelines; + let timelineCount = timelines.length; + if (i2 == 0 && mix == 1 || blend == MixBlend.add) { + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(mix, blend); + var timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, true); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection.mixIn); + } + } else { + let timelineMode = current.timelineMode; + let firstFrame = current.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + let timeline2 = timelines[ii]; + let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup; + if (timeline2 instanceof RotateTimeline) { + this.applyRotateTimeline(timeline2, skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline2 instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, true); + } else { + Utils.webkit602BugfixHelper(mix, blend); + timeline2.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, MixDirection.mixIn); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton, blend) { + let from = to.mixingFrom; + if (from.mixingFrom) + this.applyMixingFrom(from, skeleton, blend); + let mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == MixBlend.first) + blend = MixBlend.setup; + } else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != MixBlend.first) + blend = from.mixBlend; + } + let attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + let timelines = from.animation.timelines; + let timelineCount = timelines.length; + let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + if (blend == MixBlend.add) { + for (let i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.mixOut); + } else { + let timelineMode = from.timelineMode; + let timelineHoldMix = from.timelineHoldMix; + let firstFrame = from.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + from.timelinesRotation.length = timelineCount << 1; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + let timeline = timelines[i]; + let direction = MixDirection.mixOut; + let timelineBlend; + let alpha = 0; + switch (timelineMode[i]) { + case SUBSEQUENT: + if (!drawOrder && timeline instanceof DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = MixBlend.setup; + alpha = alphaMix; + break; + case HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case HOLD_FIRST: + timelineBlend = MixBlend.setup; + alpha = alphaHold; + break; + default: + timelineBlend = MixBlend.setup; + let holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments); + else { + Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == MixBlend.setup) + direction = MixDirection.mixIn; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) + return; + if (time < timeline.frames[0]) { + if (blend == MixBlend.setup || blend == MixBlend.first) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } else + this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments); + if (slot.attachmentState <= this.unkeyedState) + slot.attachmentState = this.unkeyedState + SETUP; + } + setAttachment(skeleton, slot, attachmentName, attachments) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) + slot.attachmentState = this.unkeyedState + CURRENT; + } + applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.mixIn); + return; + } + let bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) + return; + let frames = timeline.frames; + let r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case MixBlend.setup: + bone.rotation = bone.data.rotation; + default: + return; + case MixBlend.first: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } else { + r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation; + r2 = bone.data.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= (16384 - (16384.499999999996 - diff / 360 | 0)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + let current = diff > 0, dir = lastTotal >= 0; + if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + let animationStart = entry.animationStart, animationEnd = entry.animationEnd; + let duration = animationEnd - animationStart; + let trackLastWrapped = entry.trackLast % duration; + let events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + let event = events[i]; + if (event.time < trackLastWrapped) + break; + if (event.time > animationEnd) + continue; + this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + let event = events[i]; + if (event.time < animationStart) + continue; + this.queue.event(entry, event); + } + } + clearTracks() { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + clearTrack(trackIndex) { + if (trackIndex >= this.tracks.length) + return; + let current = this.tracks[trackIndex]; + if (!current) + return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + let from = entry.mixingFrom; + if (!from) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setCurrent(index, current, interrupt) { + let from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + setAnimation(trackIndex, animationName, loop = false) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + } + setAnimationWith(trackIndex, animation, loop = false) { + if (!animation) + throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + let entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + addAnimation(trackIndex, animationName, loop = false, delay = 0) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + } + addAnimationWith(trackIndex, animation, loop = false, delay = 0) { + if (!animation) + throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + let entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) + delay += last.getTrackComplete() - entry.mixDuration; + } + entry.delay = delay; + return entry; + } + setEmptyAnimation(trackIndex, mixDuration = 0) { + let entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation(), false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + let entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation(), false, delay); + if (delay <= 0) + entry.delay += entry.mixDuration - mixDuration; + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + setEmptyAnimations(mixDuration = 0) { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + let current = this.tracks[i]; + if (current) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) + return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + trackEntry(trackIndex, animation, loop, last) { + let entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.interruptAlpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.mixBlend = MixBlend.replace; + return entry; + } + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + this.propertyIDs.clear(); + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let entry = tracks[i]; + if (!entry) + continue; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + if (!entry.mixingTo || entry.mixBlend != MixBlend.add) + this.computeHold(entry); + entry = entry.mixingTo; + } while (entry); + } + } + computeHold(entry) { + let to = entry.mixingTo; + let timelines = entry.animation.timelines; + let timelinesCount = entry.animation.timelines.length; + let timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + let timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + let propertyIDs = this.propertyIDs; + if (to && to.holdPrevious) { + for (let i = 0; i < timelinesCount; i++) + timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; + return; + } + outer: + for (let i = 0; i < timelinesCount; i++) { + let timeline = timelines[i]; + let ids = timeline.getPropertyIds(); + if (!propertyIDs.addAll(ids)) + timelineMode[i] = SUBSEQUENT; + else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) { + timelineMode[i] = FIRST; + } else { + for (let next = to.mixingTo; next; next = next.mixingTo) { + if (next.animation.hasTimeline(ids)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = HOLD_MIX; + timelineHoldMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = HOLD_FIRST; + } + } + } + getCurrent(trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + } + addListener(listener) { + if (!listener) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + removeListener(listener) { + let index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + } + clearListeners() { + this.listeners.length = 0; + } + clearListenerNotifications() { + this.queue.clear(); + } + }; + var TrackEntry = class { + constructor() { + this.animation = null; + this.previous = null; + this.next = null; + this.mixingFrom = null; + this.mixingTo = null; + this.listener = null; + this.trackIndex = 0; + this.loop = false; + this.holdPrevious = false; + this.reverse = false; + this.eventThreshold = 0; + this.attachmentThreshold = 0; + this.drawOrderThreshold = 0; + this.animationStart = 0; + this.animationEnd = 0; + this.animationLast = 0; + this.nextAnimationLast = 0; + this.delay = 0; + this.trackTime = 0; + this.trackLast = 0; + this.nextTrackLast = 0; + this.trackEnd = 0; + this.timeScale = 0; + this.alpha = 0; + this.mixTime = 0; + this.mixDuration = 0; + this.interruptAlpha = 0; + this.totalAlpha = 0; + this.mixBlend = MixBlend.replace; + this.timelineMode = new Array(); + this.timelineHoldMix = new Array(); + this.timelinesRotation = new Array(); + } + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + getAnimationTime() { + if (this.loop) { + let duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + getTrackComplete() { + let duration = this.animationEnd - this.animationStart; + if (duration != 0) { + if (this.loop) + return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) + return duration; + } + return this.trackTime; + } + }; + var EventQueue = class { + constructor(animState) { + this.objects = []; + this.drainDisabled = false; + this.animState = null; + this.animState = animState; + } + start(entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + } + end(entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) + return; + this.drainDisabled = true; + let objects = this.objects; + let listeners = this.animState.listeners; + for (let i = 0; i < objects.length; i += 2) { + let type = objects[i]; + let entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener && entry.listener.start) + entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].start) + listeners[ii].start(entry); + break; + case EventType.interrupt: + if (entry.listener && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].interrupt) + listeners[ii].interrupt(entry); + break; + case EventType.end: + if (entry.listener && entry.listener.end) + entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].end) + listeners[ii].end(entry); + case EventType.dispose: + if (entry.listener && entry.listener.dispose) + entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].dispose) + listeners[ii].dispose(entry); + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener && entry.listener.complete) + entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].complete) + listeners[ii].complete(entry); + break; + case EventType.event: + let event = objects[i++ + 2]; + if (entry.listener && entry.listener.event) + entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) + if (listeners[ii].event) + listeners[ii].event(entry, event); + break; + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } + }; + var EventType; + (function(EventType2) { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + })(EventType || (EventType = {})); + var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } + }; + var SUBSEQUENT = 0; + var FIRST = 1; + var HOLD_SUBSEQUENT = 2; + var HOLD_FIRST = 3; + var HOLD_MIX = 4; + var SETUP = 1; + var CURRENT = 2; + var _emptyAnimation = null; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + constructor(skeletonData) { + this.skeletonData = null; + this.animationToMixTime = {}; + this.defaultMix = 0; + if (!skeletonData) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + setMix(fromName, toName, duration) { + let from = this.skeletonData.findAnimation(fromName); + if (!from) + throw new Error("Animation not found: " + fromName); + let to = this.skeletonData.findAnimation(toName); + if (!to) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + } + setMixWith(from, to, duration) { + if (!from) + throw new Error("from cannot be null."); + if (!to) + throw new Error("to cannot be null."); + let key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + } + getMix(from, to) { + let key = from.name + "." + to.name; + let value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } + }; + + // spine-core/src/attachments/BoundingBoxAttachment.ts + var BoundingBoxAttachment = class extends VertexAttachment { + constructor(name) { + super(name); + this.color = new Color(1, 1, 1, 1); + } + copy() { + let copy = new BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/ClippingAttachment.ts + var ClippingAttachment = class extends VertexAttachment { + constructor(name) { + super(name); + this.endSlot = null; + this.color = new Color(0.2275, 0.2275, 0.8078, 1); + } + copy() { + let copy = new ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/Texture.ts + var Texture = class { + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } + }; + var TextureFilter; + (function(TextureFilter3) { + TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest"; + TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear"; + TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap"; + TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(TextureFilter || (TextureFilter = {})); + var TextureWrap; + (function(TextureWrap3) { + TextureWrap3[TextureWrap3["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap3[TextureWrap3["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap3[TextureWrap3["Repeat"] = 10497] = "Repeat"; + })(TextureWrap || (TextureWrap = {})); + var TextureRegion = class { + constructor() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.degrees = 0; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + }; + var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-core/src/TextureAtlas.ts + var TextureAtlas = class { + constructor(atlasText) { + this.pages = new Array(); + this.regions = new Array(); + let reader = new TextureAtlasReader(atlasText); + let entry = new Array(4); + let page = null; + let region = null; + let pageFields = {}; + pageFields["size"] = () => { + page.width = parseInt(entry[1]); + page.height = parseInt(entry[2]); + }; + pageFields["format"] = () => { + }; + pageFields["filter"] = () => { + page.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields["repeat"] = () => { + if (entry[1].indexOf("x") != -1) + page.uWrap = TextureWrap.Repeat; + if (entry[1].indexOf("y") != -1) + page.vWrap = TextureWrap.Repeat; + }; + pageFields["pma"] = () => { + page.pma = entry[1] == "true"; + }; + var regionFields = {}; + regionFields["xy"] = () => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields["size"] = () => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields["bounds"] = () => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields["offset"] = () => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields["orig"] = () => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields["offsets"] = () => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields["rotate"] = () => { + let value = entry[1]; + if (value == "true") + region.degrees = 90; + else if (value != "false") + region.degrees = parseInt(value); + }; + regionFields["index"] = () => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length == 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length == 0) + break; + if (reader.readEntry(entry, line) == 0) + break; + line = reader.readLine(); + } + let names = null; + let values = null; + while (true) { + if (line === null) + break; + if (line.trim().length == 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(); + page.name = line.trim(); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) == 0) + break; + let field = pageFields[entry[0]]; + if (field) + field(); + } + this.pages.push(page); + } else { + region = new TextureAtlasRegion(); + region.page = page; + region.name = line; + while (true) { + let count = reader.readEntry(entry, line = reader.readLine()); + if (count == 0) + break; + let field = regionFields[entry[0]]; + if (field) + field(); + else { + if (!names) { + names = []; + values = []; + } + names.push(entry[0]); + let entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth == 0 && region.originalHeight == 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees == 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (let page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + } + }; + var TextureAtlasReader = class { + constructor(text) { + this.lines = null; + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) + return 0; + line = line.trim(); + if (line.length == 0) + return 0; + let colon = line.indexOf(":"); + if (colon == -1) + return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + let comma = line.indexOf(",", lastMatch); + if (comma == -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) + return 4; + } + } + }; + var TextureAtlasPage = class { + constructor() { + this.name = null; + this.minFilter = TextureFilter.Nearest; + this.magFilter = TextureFilter.Nearest; + this.uWrap = TextureWrap.ClampToEdge; + this.vWrap = TextureWrap.ClampToEdge; + this.texture = null; + this.width = 0; + this.height = 0; + this.pma = false; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + } + }; + var TextureAtlasRegion = class extends TextureRegion { + constructor() { + super(...arguments); + this.page = null; + this.name = null; + this.x = 0; + this.y = 0; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + this.index = 0; + this.degrees = 0; + this.names = null; + this.values = null; + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class extends VertexAttachment { + constructor(name) { + super(name); + this.region = null; + this.path = null; + this.regionUVs = null; + this.uvs = null; + this.triangles = null; + this.color = new Color(1, 1, 1, 1); + this.width = 0; + this.height = 0; + this.hullLength = 0; + this.edges = null; + this.parentMesh = null; + this.tempColor = new Color(0, 0, 0, 0); + } + updateUVs() { + let regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length != regionUVs.length) + this.uvs = Utils.newFloatArray(regionUVs.length); + let uvs = this.uvs; + let n = this.uvs.length; + let u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof TextureAtlasRegion) { + let region = this.region, image = region.page.texture.getImage(); + let textureWidth = image.width, textureHeight = image.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } else if (!this.region) { + u = v = 0; + width = height = 1; + } else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + getParentMesh() { + return this.parentMesh; + } + setParentMesh(parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + } + copy() { + if (this.parentMesh) + return this.newLinkedMesh(); + let copy = new MeshAttachment(this.name); + copy.region = this.region; + copy.path = this.path; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = new Array(this.uvs.length); + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + if (this.edges) { + copy.edges = new Array(this.edges.length); + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + newLinkedMesh() { + let copy = new MeshAttachment(this.name); + copy.region = this.region; + copy.path = this.path; + copy.color.setFromColor(this.color); + copy.deformAttachment = this.deformAttachment; + copy.setParentMesh(this.parentMesh ? this.parentMesh : this); + copy.updateUVs(); + return copy; + } + }; + + // spine-core/src/attachments/PathAttachment.ts + var PathAttachment = class extends VertexAttachment { + constructor(name) { + super(name); + this.lengths = null; + this.closed = false; + this.constantSpeed = false; + this.color = new Color(1, 1, 1, 1); + } + copy() { + let copy = new PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PointAttachment.ts + var PointAttachment = class extends VertexAttachment { + constructor(name) { + super(name); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.color = new Color(0.38, 0.94, 0, 1); + } + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + computeWorldRotation(bone) { + let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation); + let x = cos * bone.a + sin * bone.b; + let y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * MathUtils.radDeg; + } + copy() { + let copy = new PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/RegionAttachment.ts + var _RegionAttachment = class extends Attachment { + constructor(name) { + super(name); + this.x = 0; + this.y = 0; + this.scaleX = 1; + this.scaleY = 1; + this.rotation = 0; + this.width = 0; + this.height = 0; + this.color = new Color(1, 1, 1, 1); + this.path = null; + this.rendererObject = null; + this.region = null; + this.offset = Utils.newFloatArray(8); + this.uvs = Utils.newFloatArray(8); + this.tempColor = new Color(1, 1, 1, 1); + } + updateOffset() { + let region = this.region; + let regionScaleX = this.width / this.region.originalWidth * this.scaleX; + let regionScaleY = this.height / this.region.originalHeight * this.scaleY; + let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + let localX2 = localX + this.region.width * regionScaleX; + let localY2 = localY + this.region.height * regionScaleY; + let radians = this.rotation * Math.PI / 180; + let cos = Math.cos(radians); + let sin = Math.sin(radians); + let x = this.x, y = this.y; + let localXCos = localX * cos + x; + let localXSin = localX * sin; + let localYCos = localY * cos + y; + let localYSin = localY * sin; + let localX2Cos = localX2 * cos + x; + let localX2Sin = localX2 * sin; + let localY2Cos = localY2 * cos + y; + let localY2Sin = localY2 * sin; + let offset = this.offset; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + } + setRegion(region) { + this.region = region; + let uvs = this.uvs; + if (region.degrees == 90) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; + } else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + } + computeWorldVertices(bone, worldVertices, offset, stride) { + let vertexOffset = this.offset; + let x = bone.worldX, y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = 0, offsetY = 0; + offsetX = vertexOffset[0]; + offsetY = vertexOffset[1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[2]; + offsetY = vertexOffset[3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[4]; + offsetY = vertexOffset[5]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[6]; + offsetY = vertexOffset[7]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + } + copy() { + let copy = new _RegionAttachment(this.name); + copy.region = this.region; + copy.rendererObject = this.rendererObject; + copy.path = this.path; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + return copy; + } + }; + var RegionAttachment = _RegionAttachment; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + + // spine-core/src/AtlasAttachmentLoader.ts + var AtlasAttachmentLoader = class { + constructor(atlas) { + this.atlas = null; + this.atlas = atlas; + } + newRegionAttachment(skin, name, path) { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + region.renderObject = region; + let attachment = new RegionAttachment(name); + attachment.setRegion(region); + return attachment; + } + newMeshAttachment(skin, name, path) { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + region.renderObject = region; + let attachment = new MeshAttachment(name); + attachment.region = region; + return attachment; + } + newBoundingBoxAttachment(skin, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, name) { + return new ClippingAttachment(name); + } + }; + + // spine-core/src/BoneData.ts + var BoneData = class { + constructor(index, name, parent) { + this.index = 0; + this.name = null; + this.parent = null; + this.length = 0; + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 1; + this.scaleY = 1; + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + this.skinRequired = false; + this.color = new Color(); + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + }; + var TransformMode; + (function(TransformMode2) { + TransformMode2[TransformMode2["Normal"] = 0] = "Normal"; + TransformMode2[TransformMode2["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode2[TransformMode2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode2[TransformMode2["NoScale"] = 3] = "NoScale"; + TransformMode2[TransformMode2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(TransformMode || (TransformMode = {})); + + // spine-core/src/Bone.ts + var Bone = class { + constructor(data, skeleton, parent) { + this.data = null; + this.skeleton = null; + this.parent = null; + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.a = 0; + this.b = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.worldX = 0; + this.sorted = false; + this.active = false; + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + isActive() { + return this.active; + } + update() { + this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY); + } + updateWorldTransform() { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + } + updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + let parent = this.parent; + if (!parent) { + let skeleton = this.skeleton; + let rotationY = rotation + 90 + shearY; + let sx = skeleton.scaleX; + let sy = skeleton.scaleY; + this.a = MathUtils.cosDeg(rotation + shearX) * scaleX * sx; + this.b = MathUtils.cosDeg(rotationY) * scaleY * sx; + this.c = MathUtils.sinDeg(rotation + shearX) * scaleX * sy; + this.d = MathUtils.sinDeg(rotationY) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case TransformMode.Normal: { + let rotationY = rotation + 90 + shearY; + let la = MathUtils.cosDeg(rotation + shearX) * scaleX; + let lb = MathUtils.cosDeg(rotationY) * scaleY; + let lc = MathUtils.sinDeg(rotation + shearX) * scaleX; + let ld = MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case TransformMode.OnlyTranslation: { + let rotationY = rotation + 90 + shearY; + this.a = MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = MathUtils.cosDeg(rotationY) * scaleY; + this.c = MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case TransformMode.NoRotationOrReflection: { + let s = pa * pa + pc * pc; + let prx = 0; + if (s > 1e-4) { + s = Math.abs(pa * pd - pb * pc) / s; + pa /= this.skeleton.scaleX; + pc /= this.skeleton.scaleY; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * MathUtils.radDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg; + } + let rx = rotation + shearX - prx; + let ry = rotation + shearY - prx + 90; + let la = MathUtils.cosDeg(rx) * scaleX; + let lb = MathUtils.cosDeg(ry) * scaleY; + let lc = MathUtils.sinDeg(rx) * scaleX; + let ld = MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case TransformMode.NoScale: + case TransformMode.NoScaleOrReflection: { + let cos = MathUtils.cosDeg(rotation); + let sin = MathUtils.sinDeg(rotation); + let za = (pa * cos + pb * sin) / this.skeleton.scaleX; + let zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(za * za + zc * zc); + if (s > 1e-5) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.data.transformMode == TransformMode.NoScale && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + let r = Math.PI / 2 + Math.atan2(zc, za); + let zb = Math.cos(r) * s; + let zd = Math.sin(r) * s; + let la = MathUtils.cosDeg(shearX) * scaleX; + let lb = MathUtils.cosDeg(90 + shearY) * scaleY; + let lc = MathUtils.sinDeg(shearX) * scaleX; + let ld = MathUtils.sinDeg(90 + shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + } + setToSetupPose() { + let data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + } + getWorldRotationX() { + return Math.atan2(this.c, this.a) * MathUtils.radDeg; + } + getWorldRotationY() { + return Math.atan2(this.d, this.b) * MathUtils.radDeg; + } + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + updateAppliedTransform() { + let parent = this.parent; + if (!parent) { + this.ax = this.worldX - this.skeleton.x; + this.ay = this.worldY - this.skeleton.y; + this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + let pid = 1 / (pa * pd - pb * pc); + let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = dx * pd * pid - dy * pb * pid; + this.ay = dy * pa * pid - dx * pc * pid; + let ia = pid * pd; + let id = pid * pa; + let ib = pid * pb; + let ic = pid * pc; + let ra = ia * this.a - ib * this.c; + let rb = ia * this.b - ib * this.d; + let rc = id * this.c - ic * this.a; + let rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 1e-4) { + let det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg; + } else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg; + } + } + worldToLocal(world) { + let invDet = 1 / (this.a * this.d - this.b * this.c); + let x = world.x - this.worldX, y = world.y - this.worldY; + world.x = x * this.d * invDet - y * this.b * invDet; + world.y = y * this.a * invDet - x * this.c * invDet; + return world; + } + localToWorld(local) { + let x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + worldToLocalRotation(worldRotation) { + let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX; + } + localToWorldRotation(localRotation) { + localRotation -= this.rotation - this.shearX; + let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + rotateWorld(degrees) { + let a = this.a, b = this.b, c = this.c, d = this.d; + let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + } + }; + + // spine-core/src/ConstraintData.ts + var ConstraintData = class { + constructor(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } + }; + + // spine-core/src/AssetManagerBase.ts + var AssetManagerBase = class { + constructor(textureLoader, pathPrefix = "", downloader = null) { + this.pathPrefix = null; + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader || new Downloader(); + } + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.assets[path] = asset; + if (callback) + callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) + callback(path, message); + } + loadAll() { + let promise = new Promise((resolve, reject) => { + let check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) + reject(this.errors); + else + resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = null, error = null) { + path = this.start(path); + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`); + }); + } + loadText(path, success = null, error = null) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = null, error = null) { + path = this.start(path); + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`); + }); + } + loadTexture(path, success = null, error = null) { + path = this.start(path); + let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + let isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) + return response.blob(); + this.error(error, path, `Couldn't load image: ${path}`); + return null; + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) + this.success(success, path, this.textureLoader(bitmap)); + }); + } else { + let image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + this.success(success, path, this.textureLoader(image)); + }; + image.onerror = () => { + this.error(error, path, `Couldn't load image: ${path}`); + }; + if (this.downloader.rawDataUris[path]) + path = this.downloader.rawDataUris[path]; + image.src = path; + } + } + loadTextureAtlas(path, success = null, error = null, fileAlias = null) { + let index = path.lastIndexOf("/"); + let parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + this.downloader.downloadText(path, (atlasText) => { + try { + let atlas = new TextureAtlas(atlasText); + let toLoad = atlas.pages.length, abort = false; + for (let page of atlas.pages) { + this.loadTexture(fileAlias == null ? parent + page.name : fileAlias[page.name], (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad == 0) + this.success(success, path, atlas); + } + }, (imagePath, message) => { + if (!abort) + this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`); + abort = true; + }); + } + } catch (e) { + this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`); + } + }, (status, responseText) => { + this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`); + }); + } + get(path) { + return this.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset) + return asset; + let error = this.errors[path]; + throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + } + remove(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + delete this.assets[path]; + return asset; + } + removeAll() { + for (let key in this.assets) { + let asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + } + isLoadingComplete() { + return this.toLoad == 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } + }; + var Downloader = class { + constructor() { + this.callbacks = {}; + this.rawDataUris = {}; + } + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx != -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx == -1) + throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToString(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", url, true); + let done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToUint8Array(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + let onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status == 200 || request.status == 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) + return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + let callbacks = this.callbacks[url]; + delete this.callbacks[url]; + let args = status == 200 || status == 0 ? [data] : [status, data]; + for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) + callbacks[i].apply(null, args); + } + }; + + // spine-core/src/Event.ts + var Event = class { + constructor(time, data) { + this.data = null; + this.intValue = 0; + this.floatValue = 0; + this.stringValue = null; + this.time = 0; + this.volume = 0; + this.balance = 0; + if (!data) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + }; + + // spine-core/src/EventData.ts + var EventData = class { + constructor(name) { + this.name = null; + this.intValue = 0; + this.floatValue = 0; + this.stringValue = null; + this.audioPath = null; + this.volume = 0; + this.balance = 0; + this.name = name; + } + }; + + // spine-core/src/IkConstraint.ts + var IkConstraint = class { + constructor(data, skeleton) { + this.data = null; + this.bones = null; + this.target = null; + this.bendDirection = 0; + this.compress = false; + this.stretch = false; + this.mix = 1; + this.softness = 0; + this.active = false; + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + isActive() { + return this.active; + } + update() { + if (this.mix == 0) + return; + let target = this.target; + let bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix); + break; + } + } + apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) { + let p = bone.parent; + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.data.transformMode) { + case TransformMode.OnlyTranslation: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + break; + case TransformMode.NoRotationOrReflection: + let s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + let sa = pa / bone.skeleton.scaleX; + let sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg; + default: + let x = targetX - p.worldX, y = targetY - p.worldY; + let d = pa * pd - pb * pc; + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + let sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.data.transformMode) { + case TransformMode.NoScale: + case TransformMode.NoScaleOrReflection: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); + if (compress && dd < b || stretch && dd > b && b > 1e-4) { + let s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); + } + apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) { + let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + let u = Math.abs(psx - psy) <= 1e-4; + if (!u || stretch) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + let pp = parent.parent; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = 1 / (a * d - b * c), x = cwx - pp.worldX, y = cwy - pp.worldY; + let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 1e-4) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5; + let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) + sy *= a; + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + let c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + let os = Math.atan2(cy, cx) * s2; + let rotation = parent.arotation; + a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + } + }; + + // spine-core/src/IkConstraintData.ts + var IkConstraintData = class extends ConstraintData { + constructor(name) { + super(name, 0, false); + this.bones = new Array(); + this.target = null; + this.bendDirection = 1; + this.compress = false; + this.stretch = false; + this.uniform = false; + this.mix = 1; + this.softness = 0; + } + }; + + // spine-core/src/PathConstraintData.ts + var PathConstraintData = class extends ConstraintData { + constructor(name) { + super(name, 0, false); + this.bones = new Array(); + this.target = null; + this.positionMode = null; + this.spacingMode = null; + this.rotateMode = null; + this.offsetRotation = 0; + this.position = 0; + this.spacing = 0; + this.mixRotate = 0; + this.mixX = 0; + this.mixY = 0; + } + }; + var PositionMode; + (function(PositionMode2) { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + })(PositionMode || (PositionMode = {})); + var SpacingMode; + (function(SpacingMode2) { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + })(SpacingMode || (SpacingMode = {})); + var RotateMode; + (function(RotateMode2) { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + })(RotateMode || (RotateMode = {})); + + // spine-core/src/PathConstraint.ts + var _PathConstraint = class { + constructor(data, skeleton) { + this.data = null; + this.bones = null; + this.target = null; + this.position = 0; + this.spacing = 0; + this.mixRotate = 0; + this.mixX = 0; + this.mixY = 0; + this.spaces = new Array(); + this.positions = new Array(); + this.world = new Array(); + this.curves = new Array(); + this.lengths = new Array(); + this.segments = new Array(); + this.active = false; + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0, n = data.bones.length; i < n; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findSlot(data.target.name); + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + isActive() { + return this.active; + } + update() { + let attachment = this.target.getAttachment(); + if (!(attachment instanceof PathAttachment)) + return; + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) + return; + let data = this.data; + let tangents = data.rotateMode == RotateMode.Tangent, scale = data.rotateMode == RotateMode.ChainScale; + let bones = this.bones; + let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : null; + let spacing = this.spacing; + switch (data.spacingMode) { + case SpacingMode.Percent: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) + lengths[i] = 0; + else { + let x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case SpacingMode.Proportional: + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + let lengthSpacing = data.spacingMode == SpacingMode.Length; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + let positions = this.computeWorldPositions(attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation == 0) + tip = data.rotateMode == RotateMode.Chain; + else { + tip = false; + let p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, p = 3; i < boneCount; i++, p += 3) { + let bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + let length = lengths[i]; + if (length != 0) { + let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + let length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.updateAppliedTransform(); + } + } + computeWorldPositions(path, spacesCount, tangents) { + let target = this.target; + let position = this.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null; + let closed2 = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + let lengths = path.lengths; + curveCount -= closed2 ? 1 : 2; + let pathLength2 = lengths[curveCount]; + if (this.data.positionMode == PositionMode.Percent) + position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case SpacingMode.Percent: + multiplier2 = pathLength2; + break; + case SpacingMode.Proportional: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed2) { + p %= pathLength2; + if (p < 0) + p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve != _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve != _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + let length = lengths[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed2 && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || i > 0 && space == 0); + } + return out; + } + if (closed2) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + let curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode == PositionMode.Percent) + position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case SpacingMode.Percent: + multiplier = pathLength; + break; + case SpacingMode.Proportional: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + let segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed2) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + let length = curves[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + let length = segments[segment]; + if (p > length) + continue; + if (segment == 0) + p /= length; + else { + let prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } + }; + var PathConstraint = _PathConstraint; + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; + PathConstraint.epsilon = 1e-5; + + // spine-core/src/Slot.ts + var Slot = class { + constructor(data, bone) { + this.data = null; + this.bone = null; + this.color = null; + this.darkColor = null; + this.attachment = null; + this.attachmentTime = 0; + this.attachmentState = 0; + this.deform = new Array(); + if (!data) + throw new Error("data cannot be null."); + if (!bone) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new Color(); + this.darkColor = !data.darkColor ? null : new Color(); + this.setToSetupPose(); + } + getSkeleton() { + return this.bone.skeleton; + } + getAttachment() { + return this.attachment; + } + setAttachment(attachment) { + if (this.attachment == attachment) + return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.deformAttachment != this.attachment.deformAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + } + setAttachmentTime(time) { + this.attachmentTime = this.bone.skeleton.time - time; + } + getAttachmentTime() { + return this.bone.skeleton.time - this.attachmentTime; + } + setToSetupPose() { + this.color.setFromColor(this.data.color); + if (this.darkColor) + this.darkColor.setFromColor(this.data.darkColor); + if (!this.data.attachmentName) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } + }; + + // spine-core/src/TransformConstraint.ts + var TransformConstraint = class { + constructor(data, skeleton) { + this.data = null; + this.bones = null; + this.target = null; + this.mixRotate = 0; + this.mixX = 0; + this.mixY = 0; + this.mixScaleX = 0; + this.mixScaleY = 0; + this.mixShearY = 0; + this.temp = new Vector2(); + this.active = false; + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + isActive() { + return this.active; + } + update() { + if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleX == 0 && this.mixShearY == 0) + return; + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + } + applyAbsoluteWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect; + let offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * mixX; + bone.worldY += (temp.y - bone.worldY) * mixY; + } + if (mixScaleX != 0) { + let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + if (s != 0) + s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + if (s != 0) + s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let b = bone.b, d = bone.d; + let by = Math.atan2(d, b); + let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r = by + (r + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyRelativeWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * mixX; + bone.worldY += temp.y * mixY; + } + if (mixScaleX != 0) { + let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + let b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyAbsoluteLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation; + if (mixRotate != 0) { + let r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360; + rotation += r * mixRotate; + } + let x = bone.ax, y = bone.ay; + x += (target.ax - x + this.data.offsetX) * mixX; + y += (target.ay - y + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY; + let shearY = bone.ashearY; + if (mixShearY != 0) { + let r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360; + shearY += r * mixShearY; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + applyRelativeLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax + (target.ax + this.data.offsetX) * mixX; + let y = bone.ay + (target.ay + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1); + let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1); + let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + }; + + // spine-core/src/Skeleton.ts + var Skeleton = class { + constructor(data) { + this.data = null; + this.bones = null; + this.slots = null; + this.drawOrder = null; + this.ikConstraints = null; + this.transformConstraints = null; + this.pathConstraints = null; + this._updateCache = new Array(); + this.skin = null; + this.color = null; + this.time = 0; + this.scaleX = 1; + this.scaleY = 1; + this.x = 0; + this.y = 0; + if (!data) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, this, null); + else { + let parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (let i = 0; i < data.slots.length; i++) { + let slotData = data.slots[i]; + let bone = this.bones[slotData.boneData.index]; + let slot = new Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (let i = 0; i < data.ikConstraints.length; i++) { + let ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (let i = 0; i < data.transformConstraints.length; i++) { + let transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (let i = 0; i < data.pathConstraints.length; i++) { + let pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new PathConstraint(pathConstraintData, this)); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + updateCache() { + let updateCache = this._updateCache; + updateCache.length = 0; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin) { + let skinBones = this.skin.bones; + for (let i = 0, n = this.skin.bones.length; i < n; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + let ikConstraints = this.ikConstraints; + let transformConstraints = this.transformConstraints; + let pathConstraints = this.pathConstraints; + let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + let constraintCount = ikCount + transformCount + pathCount; + outer: + for (let i = 0; i < constraintCount; i++) { + for (let ii = 0; ii < ikCount; ii++) { + let constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < transformCount; ii++) { + let constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < pathCount; ii++) { + let constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (let i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + } + sortIkConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let target = constraint.target; + this.sortBone(target); + let constrained = constraint.bones; + let parent = constrained[0]; + this.sortBone(parent); + if (constrained.length == 1) { + this._updateCache.push(constraint); + this.sortReset(parent.children); + } else { + let child = constrained[constrained.length - 1]; + this.sortBone(child); + this._updateCache.push(constraint); + this.sortReset(parent.children); + child.sorted = true; + } + } + sortPathConstraint(constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let slot = constraint.target; + let slotIndex = slot.data.index; + let slotBone = slot.bone; + if (this.skin) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (let i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + let attachment = slot.getAttachment(); + if (attachment instanceof PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + let constrained = constraint.bones; + let boneCount = constrained.length; + for (let i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortTransformConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(constraint.target); + let constrained = constraint.bones; + let boneCount = constrained.length; + if (constraint.data.local) { + for (let i = 0; i < boneCount; i++) { + let child = constrained[i]; + this.sortBone(child.parent); + this.sortBone(child); + } + } else { + for (let i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortPathConstraintAttachment(skin, slotIndex, slotBone) { + let attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (let key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + } + sortPathConstraintAttachmentWith(attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) + return; + let pathBones = attachment.bones; + if (!pathBones) + this.sortBone(slotBone); + else { + let bones = this.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + this.sortBone(bones[pathBones[i++]]); + } + } + } + sortBone(bone) { + if (bone.sorted) + return; + let parent = bone.parent; + if (parent) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (!bone.active) + continue; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + } + updateWorldTransform() { + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + } + updateWorldTransformWith(parent) { + let rootBone = this.getRootBone(); + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + rootBone.worldX = pa * this.x + pb * this.y + parent.worldX; + rootBone.worldY = pc * this.x + pd * this.y + parent.worldY; + let rotationY = rootBone.rotation + 90 + rootBone.shearY; + let la = MathUtils.cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX; + let lb = MathUtils.cosDeg(rotationY) * rootBone.scaleY; + let lc = MathUtils.sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX; + let ld = MathUtils.sinDeg(rotationY) * rootBone.scaleY; + rootBone.a = (pa * la + pb * lc) * this.scaleX; + rootBone.b = (pa * lb + pb * ld) * this.scaleX; + rootBone.c = (pc * la + pd * lc) * this.scaleY; + rootBone.d = (pc * lb + pd * ld) * this.scaleY; + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) { + let updatable = updateCache[i]; + if (updatable != rootBone) + updatable.update(); + } + } + setToSetupPose() { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + } + setBonesToSetupPose() { + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let constraint = ikConstraints[i]; + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + let data = constraint.data; + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + } + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + let data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + } + } + setSlotsToSetupPose() { + let slots = this.slots; + Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + } + getRootBone() { + if (this.bones.length == 0) + return null; + return this.bones[0]; + } + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + } + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + } + setSkinByName(skinName) { + let skin = this.data.findSkin(skinName); + if (!skin) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + } + setSkin(newSkin) { + if (newSkin == this.skin) + return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let name = slot.data.attachmentName; + if (name) { + let attachment = newSkin.getAttachment(i, name); + if (attachment) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + getAttachmentByName(slotName, attachmentName) { + return this.getAttachment(this.data.findSlot(slotName).index, attachmentName); + } + getAttachment(slotIndex, attachmentName) { + if (!attachmentName) + throw new Error("attachmentName cannot be null."); + if (this.skin) { + let attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) + return attachment; + } + if (this.data.defaultSkin) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + } + setAttachment(slotName, attachmentName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) { + let attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (!attachment) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + } + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + } + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + } + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + } + getBoundsRect() { + let offset = new Vector2(); + let size = new Vector2(); + this.getBounds(offset, size); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + getBounds(offset, size, temp = new Array(2)) { + if (!offset) + throw new Error("offset cannot be null."); + if (!size) + throw new Error("size cannot be null."); + let drawOrder = this.drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + if (!slot.bone.active) + continue; + let verticesLength = 0; + let vertices = null; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices) { + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + update(delta) { + this.time += delta; + } + }; + + // spine-core/src/SkeletonData.ts + var SkeletonData = class { + constructor() { + this.name = null; + this.bones = new Array(); + this.slots = new Array(); + this.skins = new Array(); + this.defaultSkin = null; + this.events = new Array(); + this.animations = new Array(); + this.ikConstraints = new Array(); + this.transformConstraints = new Array(); + this.pathConstraints = new Array(); + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + this.version = null; + this.hash = null; + this.fps = 0; + this.imagesPath = null; + this.audioPath = null; + } + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + } + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + } + findSkin(skinName) { + if (!skinName) + throw new Error("skinName cannot be null."); + let skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) { + let skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + } + findEvent(eventDataName) { + if (!eventDataName) + throw new Error("eventDataName cannot be null."); + let events = this.events; + for (let i = 0, n = events.length; i < n; i++) { + let event = events[i]; + if (event.name == eventDataName) + return event; + } + return null; + } + findAnimation(animationName) { + if (!animationName) + throw new Error("animationName cannot be null."); + let animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) { + let animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + } + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + }; + + // spine-core/src/Skin.ts + var SkinEntry = class { + constructor(slotIndex = 0, name = null, attachment = null) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + }; + var Skin = class { + constructor(name) { + this.name = null; + this.attachments = new Array(); + this.bones = Array(); + this.constraints = new Array(); + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + setAttachment(slotIndex, name, attachment) { + if (!attachment) + throw new Error("attachment cannot be null."); + let attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + } + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (!attachment.attachment) + continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + } + getAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + } + removeAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + if (dictionary) + dictionary[name] = null; + } + getAttachments() { + let entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + let slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + getAttachmentsForSlot(slotIndex, attachments) { + let slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + let slot = skeleton.slots[i]; + let slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + let dictionary = oldSkin.attachments[slotIndex]; + for (let key in dictionary) { + let skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + let attachment = this.getAttachment(slotIndex, key); + if (attachment) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } + }; + + // spine-core/src/SlotData.ts + var SlotData = class { + constructor(index, name, boneData) { + this.index = 0; + this.name = null; + this.boneData = null; + this.color = new Color(1, 1, 1, 1); + this.darkColor = null; + this.attachmentName = null; + this.blendMode = null; + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + if (!boneData) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + }; + var BlendMode; + (function(BlendMode3) { + BlendMode3[BlendMode3["Normal"] = 0] = "Normal"; + BlendMode3[BlendMode3["Additive"] = 1] = "Additive"; + BlendMode3[BlendMode3["Multiply"] = 2] = "Multiply"; + BlendMode3[BlendMode3["Screen"] = 3] = "Screen"; + })(BlendMode || (BlendMode = {})); + + // spine-core/src/TransformConstraintData.ts + var TransformConstraintData = class extends ConstraintData { + constructor(name) { + super(name, 0, false); + this.bones = new Array(); + this.target = null; + this.mixRotate = 0; + this.mixX = 0; + this.mixY = 0; + this.mixScaleX = 0; + this.mixScaleY = 0; + this.mixShearY = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + this.relative = false; + this.local = false; + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + constructor(attachmentLoader) { + this.scale = 1; + this.attachmentLoader = null; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + skeletonData.name = ""; + let input = new BinaryInput(binary); + let lowHash = input.readInt32(); + let highHash = input.readInt32(); + skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + let nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) + input.strings.push(input.readString()); + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let name = input.readString(); + let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + let data = new BoneData(i, name, parent); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.transformMode = input.readInt(true); + data.skinRequired = input.readBoolean(); + if (nonessential) + Color.rgba8888ToColor(data.color, input.readInt32()); + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let slotName = input.readString(); + let boneData = skeletonData.bones[input.readInt(true)]; + let data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.color, input.readInt32()); + let darkColor = input.readInt32(); + if (darkColor != -1) + Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let data = new IkConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.mix = input.readFloat(); + data.softness = input.readFloat() * scale; + data.bendDirection = input.readByte(); + data.compress = input.readBoolean(); + data.stretch = input.readBoolean(); + data.uniform = input.readBoolean(); + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let data = new TransformConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.local = input.readBoolean(); + data.relative = input.readBoolean(); + data.offsetRotation = input.readFloat(); + data.offsetX = input.readFloat() * scale; + data.offsetY = input.readFloat() * scale; + data.offsetScaleX = input.readFloat(); + data.offsetScaleY = input.readFloat(); + data.offsetShearY = input.readFloat(); + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + data.mixScaleX = input.readFloat(); + data.mixScaleY = input.readFloat(); + data.mixShearY = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let data = new PathConstraintData(input.readString()); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + data.positionMode = input.readInt(true); + data.spacingMode = input.readInt(true); + data.rotateMode = input.readInt(true); + data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == PositionMode.Fixed) + data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) + data.spacing *= scale; + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) + skeletonData.skins[i] = this.readSkin(input, skeletonData, false, nonessential); + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let data = new EventData(input.readStringRef()); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) + skeletonData.animations.push(this.readAnimation(input, input.readString(), skeletonData)); + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) + return null; + skin = new Skin("default"); + } else { + skin = new Skin(input.readStringRef()); + skin.bones.length = input.readInt(true); + for (let i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let name = input.readStringRef(); + let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + if (attachment) + skin.setAttachment(slotIndex, name, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + let scale = this.scale; + let name = input.readStringRef(); + if (!name) + name = attachmentName; + switch (input.readByte()) { + case AttachmentType.Region: { + let path = input.readStringRef(); + let rotation = input.readFloat(); + let x = input.readFloat(); + let y = input.readFloat(); + let scaleX = input.readFloat(); + let scaleY = input.readFloat(); + let width = input.readFloat(); + let height = input.readFloat(); + let color = input.readInt32(); + if (!path) + path = name; + let region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (!region) + return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.updateOffset(); + return region; + } + case AttachmentType.BoundingBox: { + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let color = nonessential ? input.readInt32() : 0; + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + box.worldVerticesLength = vertexCount << 1; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(box.color, color); + return box; + } + case AttachmentType.Mesh: { + let path = input.readStringRef(); + let color = input.readInt32(); + let vertexCount = input.readInt(true); + let uvs = this.readFloatArray(input, vertexCount << 1, 1); + let triangles = this.readShortArray(input); + let vertices = this.readVertices(input, vertexCount); + let hullLength = input.readInt(true); + let edges = null; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertexCount << 1; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.hullLength = hullLength << 1; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case AttachmentType.LinkedMesh: { + let path = input.readStringRef(); + let color = input.readInt32(); + let skinName = input.readStringRef(); + let parent = input.readStringRef(); + let inheritDeform = input.readBoolean(); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinName, slotIndex, parent, inheritDeform)); + return mesh; + } + case AttachmentType.Path: { + let closed2 = input.readBoolean(); + let constantSpeed = input.readBoolean(); + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + let color = nonessential ? input.readInt32() : 0; + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = closed2; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertexCount << 1; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) + Color.rgba8888ToColor(path.color, color); + return path; + } + case AttachmentType.Point: { + let rotation = input.readFloat(); + let x = input.readFloat(); + let y = input.readFloat(); + let color = nonessential ? input.readInt32() : 0; + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) + Color.rgba8888ToColor(point.color, color); + return point; + } + case AttachmentType.Clipping: { + let endSlotIndex = input.readInt(true); + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let color = nonessential ? input.readInt32() : 0; + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertexCount << 1; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + } + readVertices(input, vertexCount) { + let scale = this.scale; + let verticesLength = vertexCount << 1; + let vertices = new Vertices(); + if (!input.readBoolean()) { + vertices.vertices = this.readFloatArray(input, verticesLength, scale); + return vertices; + } + let weights = new Array(); + let bonesArray = new Array(); + for (let i = 0; i < vertexCount; i++) { + let boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (let ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + } + readFloatArray(input, n, scale) { + let array = new Array(n); + if (scale == 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input) { + let n = input.readInt(true); + let array = new Array(n); + for (let i = 0; i < n; i++) + array[i] = input.readShort(); + return array; + } + readAnimation(input, name, skeletonData) { + input.readInt(true); + let timelines = new Array(); + let scale = this.scale; + let tempColor1 = new Color(); + let tempColor2 = new Color(); + for (let i = 0, n = input.readInt(true); i < n; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + let timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + let bezierCount = input.readInt(true); + let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + let bezierCount = input.readInt(true); + let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + let bezierCount = input.readInt(true); + let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let na = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + let bezierCount = input.readInt(true); + let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + break; + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_TRANSLATE: + timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEX: + timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEY: + timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_SCALE: + timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEX: + timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEY: + timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEAR: + timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARX: + timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARY: + timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mix = input.readFloat(), softness = input.readFloat() * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, input.readByte(), input.readBoolean(), input.readBoolean()); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mix2 = input.readFloat(), softness2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true); + let data = skeletonData.pathConstraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + switch (input.readByte()) { + case PATH_POSITION: + timelines.push(readTimeline1(input, new PathConstraintPositionTimeline(input.readInt(true), input.readInt(true), index), data.positionMode == PositionMode.Fixed ? scale : 1)); + break; + case PATH_SPACING: + timelines.push(readTimeline1(input, new PathConstraintSpacingTimeline(input.readInt(true), input.readInt(true), index), data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1)); + break; + case PATH_MIX: + let timeline = new PathConstraintMixTimeline(input.readInt(true), input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + let attachmentName = input.readStringRef(); + let attachment = skin.getAttachment(slotIndex, attachmentName); + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + let bezierCount = input.readInt(true); + let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, attachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end == 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = input.readInt(true); + end += start; + if (scale == 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + } + } + } + let drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + let timeline = new DrawOrderTimeline(drawOrderCount); + let slotCount = skeletonData.slots.length; + for (let i = 0; i < drawOrderCount; i++) { + let time = input.readFloat(); + let offsetCount = input.readInt(true); + let drawOrder = Utils.newArray(slotCount, 0); + for (let ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + let unchanged = Utils.newArray(slotCount - offsetCount, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsetCount; ii++) { + let slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + } + let eventCount = input.readInt(true); + if (eventCount > 0) { + let timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + let time = input.readFloat(); + let eventData = skeletonData.events[input.readInt(true)]; + let event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + return new Animation(name, timelines, duration); + } + }; + var BinaryInput = class { + constructor(data, strings = new Array(), index = 0, buffer = new DataView(data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + let value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + let value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + let index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + let charCount = 0; + for (let i = 0; i < byteCount; ) { + let b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + let value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() != 0; + } + }; + var LinkedMesh = class { + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritDeform = inheritDeform; + } + }; + var Vertices = class { + constructor(bones = null, vertices = null) { + this.bones = bones; + this.vertices = vertices; + } + }; + var AttachmentType; + (function(AttachmentType2) { + AttachmentType2[AttachmentType2["Region"] = 0] = "Region"; + AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh"; + AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType2[AttachmentType2["Path"] = 4] = "Path"; + AttachmentType2[AttachmentType2["Point"] = 5] = "Point"; + AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping"; + })(AttachmentType || (AttachmentType = {})); + function readTimeline1(input, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) + break; + let time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; + } + function readTimeline2(input, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) + break; + let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; + } + function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); + } + var BONE_ROTATE = 0; + var BONE_TRANSLATE = 1; + var BONE_TRANSLATEX = 2; + var BONE_TRANSLATEY = 3; + var BONE_SCALE = 4; + var BONE_SCALEX = 5; + var BONE_SCALEY = 6; + var BONE_SHEAR = 7; + var BONE_SHEARX = 8; + var BONE_SHEARY = 9; + var SLOT_ATTACHMENT = 0; + var SLOT_RGBA = 1; + var SLOT_RGB = 2; + var SLOT_RGBA2 = 3; + var SLOT_RGB2 = 4; + var SLOT_ALPHA = 5; + var PATH_POSITION = 0; + var PATH_SPACING = 1; + var PATH_MIX = 2; + var CURVE_STEPPED = 1; + var CURVE_BEZIER = 2; + + // spine-core/src/SkeletonBounds.ts + var SkeletonBounds = class { + constructor() { + this.minX = 0; + this.minY = 0; + this.maxX = 0; + this.maxY = 0; + this.boundingBoxes = new Array(); + this.polygons = new Array(); + this.polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + } + update(skeleton, updateAabb) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + let boundingBoxes = this.boundingBoxes; + let polygons = this.polygons; + let polygonPool = this.polygonPool; + let slots = skeleton.slots; + let slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (attachment instanceof BoundingBoxAttachment) { + let boundingBox = attachment; + boundingBoxes.push(boundingBox); + let polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + let vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + let x = vertices[ii]; + let y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + aabbIntersectsSegment(x1, y1, x2, y2) { + let minX = this.minX; + let minY = this.minY; + let maxX = this.maxX; + let maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + let m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + } + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + containsPoint(x, y) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + } + containsPointPolygon(polygon, x, y) { + let vertices = polygon; + let nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + let vertexY = vertices[ii + 1]; + let prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + let vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + } + intersectsSegment(x1, y1, x2, y2) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + } + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + let vertices = polygon; + let nn = polygon.length; + let width12 = x1 - x2, height12 = y1 - y2; + let det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + let x4 = vertices[ii], y4 = vertices[ii + 1]; + let det2 = x3 * y4 - y3 * x4; + let width34 = x3 - x4, height34 = y3 - y4; + let det3 = width12 * height34 - height12 * width34; + let x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + let y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + getPolygon(boundingBox) { + if (!boundingBox) + throw new Error("boundingBox cannot be null."); + let index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + } + getWidth() { + return this.maxX - this.minX; + } + getHeight() { + return this.maxY - this.minY; + } + }; + + // spine-core/src/Triangulator.ts + var Triangulator = class { + constructor() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new Pool(() => { + return new Array(); + }); + this.polygonIndicesPool = new Pool(() => { + return new Array(); + }); + } + triangulate(verticesArray) { + let vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + let indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + let isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + let triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + let p1x = vertices[p1], p1y = vertices[p1 + 1]; + let p2x = vertices[p2], p2y = vertices[p2 + 1]; + let p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + let v = indices[ii] << 1; + let vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + let previousIndex = (vertexCount + i - 1) % vertexCount; + let nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + } + decompose(verticesArray, triangles) { + let vertices = verticesArray; + let convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + let convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + let x1 = vertices[t1], y1 = vertices[t1 + 1]; + let x2 = vertices[t2], y2 = vertices[t2 + 1]; + let x3 = vertices[t3], y3 = vertices[t3 + 1]; + let merged = false; + if (fanBaseIndex == t1) { + let o = polygon.length - 4; + let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + let firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + let o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + let firstX = polygon[0], firstY = polygon[1]; + let secondX = polygon[2], secondY = polygon[3]; + let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii == i) + continue; + let otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + let otherFirstIndex = otherIndices[0]; + let otherSecondIndex = otherIndices[1]; + let otherLastIndex = otherIndices[2]; + let otherPoly = convexPolygons[ii]; + let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + let current = indices[index] << 1; + let next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + let px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + } + }; + + // spine-core/src/SkeletonClipping.ts + var SkeletonClipping = class { + constructor() { + this.triangulator = new Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + clipStart(slot, clip) { + if (this.clipAttachment) + return 0; + this.clipAttachment = clip; + let n = clip.worldVerticesLength; + let vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + let clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) { + let polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + } + clipEndWithSlot(slot) { + if (this.clipAttachment && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + } + clipEnd() { + if (!this.clipAttachment) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = this.clippingPolygons.length; + let vertexSize = twoColor ? 12 : 8; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (let ii = 0; ii < clipOutputLength; ii += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + s += 3; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + continue outer; + } + } + } + } + clip(x1, y1, x2, y2, x3, y3, clippingArea, output) { + let originalOutput = output; + let clipped = false; + let input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + let clippingVertices = clippingArea; + let clippingVerticesLast = clippingArea.length - 4; + for (let i = 0; ; i += 2) { + let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + let edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + let deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + let inputVertices = input; + let inputVerticesLength = input.length - 2, outputStart = output.length; + for (let ii = 0; ii < inputVerticesLength; ii += 2) { + let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + let inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + let side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + let c0 = inputY2 - inputY, c2 = inputX2 - inputX; + let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 1e-6) { + let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } else { + output.push(edgeX); + output.push(edgeY); + } + } else if (side2) { + let c0 = inputY2 - inputY, c2 = inputX2 - inputX; + let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 1e-6) { + let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } else { + output.push(edgeX); + output.push(edgeY); + } + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + let temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + static makeClockwise(polygon) { + let vertices = polygon; + let verticeslength = polygon.length; + let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (let i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + let x = vertices[i], y = vertices[i + 1]; + let other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + } + }; + + // spine-core/src/SkeletonJson.ts + var SkeletonJson = class { + constructor(attachmentLoader) { + this.attachmentLoader = null; + this.scale = 1; + this.linkedMeshes = new Array(); + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(json) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + let root = typeof json === "string" ? JSON.parse(json) : json; + let skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + let boneMap = root.bones[i]; + let parent = null; + let parentName = getValue(boneMap, "parent", null); + if (parentName) + parent = skeletonData.findBone(parentName); + let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + data.x = getValue(boneMap, "x", 0) * scale; + data.y = getValue(boneMap, "y", 0) * scale; + data.rotation = getValue(boneMap, "rotation", 0); + data.scaleX = getValue(boneMap, "scaleX", 1); + data.scaleY = getValue(boneMap, "scaleY", 1); + data.shearX = getValue(boneMap, "shearX", 0); + data.shearY = getValue(boneMap, "shearY", 0); + data.transformMode = Utils.enumValue(TransformMode, getValue(boneMap, "transform", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + let color = getValue(boneMap, "color", null); + if (color) + data.color.setFromString(color); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + let slotMap = root.slots[i]; + let boneData = skeletonData.findBone(slotMap.bone); + let data = new SlotData(skeletonData.slots.length, slotMap.name, boneData); + let color = getValue(slotMap, "color", null); + if (color) + data.color.setFromString(color); + let dark = getValue(slotMap, "dark", null); + if (dark) + data.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (let i = 0; i < root.ik.length; i++) { + let constraintMap = root.ik[i]; + let data = new IkConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) + data.bones.push(skeletonData.findBone(constraintMap.bones[ii])); + data.target = skeletonData.findBone(constraintMap.target); + data.mix = getValue(constraintMap, "mix", 1); + data.softness = getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = getValue(constraintMap, "compress", false); + data.stretch = getValue(constraintMap, "stretch", false); + data.uniform = getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (let i = 0; i < root.transform.length; i++) { + let constraintMap = root.transform[i]; + let data = new TransformConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) + data.bones.push(skeletonData.findBone(constraintMap.bones[ii])); + let targetName = constraintMap.target; + data.target = skeletonData.findBone(targetName); + data.local = getValue(constraintMap, "local", false); + data.relative = getValue(constraintMap, "relative", false); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.offsetX = getValue(constraintMap, "x", 0) * scale; + data.offsetY = getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = getValue(constraintMap, "scaleY", 0); + data.offsetShearY = getValue(constraintMap, "shearY", 0); + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + data.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX); + data.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (let i = 0; i < root.path.length; i++) { + let constraintMap = root.path[i]; + let data = new PathConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) + data.bones.push(skeletonData.findBone(constraintMap.bones[ii])); + let targetName = constraintMap.target; + data.target = skeletonData.findSlot(targetName); + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.position = getValue(constraintMap, "position", 0); + if (data.positionMode == PositionMode.Fixed) + data.position *= scale; + data.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) + data.spacing *= scale; + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + let skinMap = root.skins[i]; + let skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) + skin.bones.push(skeletonData.findBone(skinMap.bones[ii])); + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) + skin.constraints.push(skeletonData.findIkConstraint(skinMap.ik[ii])); + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) + skin.constraints.push(skeletonData.findTransformConstraint(skinMap.transform[ii])); + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) + skin.constraints.push(skeletonData.findPathConstraint(skinMap.path[ii])); + } + for (let slotName in skinMap.attachments) { + let slot = skeletonData.findSlot(slotName); + let slotMap = skinMap.attachments[slotName]; + for (let entryName in slotMap) { + let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) + skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + linkedMesh.mesh.updateUVs(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (let eventName in root.events) { + let eventMap = root.events[eventName]; + let data = new EventData(eventName); + data.intValue = getValue(eventMap, "int", 0); + data.floatValue = getValue(eventMap, "float", 0); + data.stringValue = getValue(eventMap, "string", ""); + data.audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + data.volume = getValue(eventMap, "volume", 1); + data.balance = getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (let animationName in root.animations) { + let animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + } + readAttachment(map, skin, slotIndex, name, skeletonData) { + let scale = this.scale; + name = getValue(map, "name", name); + switch (getValue(map, "type", "region")) { + case "region": { + let path = getValue(map, "path", name); + let region = this.attachmentLoader.newRegionAttachment(skin, name, path); + if (!region) + return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + let color = getValue(map, "color", null); + if (color) + region.color.setFromString(color); + region.updateOffset(); + return region; + } + case "boundingbox": { + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + this.readVertices(map, box, map.vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + let path = getValue(map, "path", name); + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); + if (!mesh) + return null; + mesh.path = path; + let color = getValue(map, "color", null); + if (color) + mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + let parent = getValue(map, "parent", null); + if (parent) { + this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "deform", true))); + return mesh; + } + let uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.updateUVs(); + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + let vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + let color = getValue(map, "color", null); + if (color) + path.color.setFromString(color); + return path; + } + case "point": { + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + let color = getValue(map, "color", null); + if (color) + point.color.setFromString(color); + return point; + } + case "clipping": { + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + let end = getValue(map, "end", null); + if (end) + clip.endSlot = skeletonData.findSlot(end); + let vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + clip.color.setFromString(color); + return clip; + } + } + return null; + } + readVertices(map, attachment, verticesLength) { + let scale = this.scale; + attachment.worldVerticesLength = verticesLength; + let vertices = map.vertices; + if (verticesLength == vertices.length) { + let scaledVertices = Utils.toFloatArray(vertices); + if (scale != 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + let weights = new Array(); + let bones = new Array(); + for (let i = 0, n = vertices.length; i < n; ) { + let boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + readAnimation(map, name, skeletonData) { + let scale = this.scale; + let timelines = new Array(); + if (map.slots) { + for (let slotName in map.slots) { + let slotMap = map.slots[slotName]; + let slotIndex = skeletonData.findSlot(slotName).index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + if (!timelineMap) + continue; + let frames = timelineMap.length; + if (timelineName == "attachment") { + let timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + let keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), keyMap.name); + } + timelines.push(timeline); + } else if (timelineName == "rgba") { + let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb") { + let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "alpha") { + timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1)); + } else if (timelineName == "rgba2") { + let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb2") { + let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.bones) { + for (let boneName in map.bones) { + let boneMap = map.bones[boneName]; + let boneIndex = skeletonData.findBone(boneName).index; + for (let timelineName in boneMap) { + let timelineMap = boneMap[timelineName]; + let frames = timelineMap.length; + if (frames == 0) + continue; + if (timelineName === "rotate") { + timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1)); + } else if (timelineName === "translate") { + let timeline = new TranslateTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale)); + } else if (timelineName === "translatex") { + let timeline = new TranslateXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "translatey") { + let timeline = new TranslateYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "scale") { + let timeline = new ScaleTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1)); + } else if (timelineName === "scalex") { + let timeline = new ScaleXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "scaley") { + let timeline = new ScaleYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "shear") { + let timeline = new ShearTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1)); + } else if (timelineName === "shearx") { + let timeline = new ShearXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "sheary") { + let timeline = new ShearYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } + } + } + } + if (map.ik) { + for (let constraintName in map.ik) { + let constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findIkConstraint(constraintName); + let constraintIndex = skeletonData.ikConstraints.indexOf(constraint); + let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + let nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mix2 = getValue(nextMap, "mix", 1); + let softness2 = getValue(nextMap, "softness", 0) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (let constraintName in map.transform) { + let timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findTransformConstraint(constraintName); + let constraintIndex = skeletonData.transformConstraints.indexOf(constraint); + let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1); + let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let mixScaleX2 = getValue(nextMap, "mixScaleX", 1); + let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2); + let mixShearY2 = getValue(nextMap, "mixShearY", 1); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (let constraintName in map.path) { + let constraintMap = map.path[constraintName]; + let constraint = skeletonData.findPathConstraint(constraintName); + let constraintIndex = skeletonData.pathConstraints.indexOf(constraint); + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName === "position") { + let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1)); + } else if (timelineName === "spacing") { + let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1)); + } else if (timelineName === "mix") { + let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.deform) { + for (let deformName in map.deform) { + let deformMap = map.deform[deformName]; + let skin = skeletonData.findSkin(deformName); + for (let slotName in deformMap) { + let slotMap = deformMap[slotName]; + let slotIndex = skeletonData.findSlot(slotName).index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let attachment = skin.getAttachment(slotIndex, timelineName); + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let curve = keyMap.curve; + if (curve) + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.drawOrder) { + let timeline = new DrawOrderTimeline(map.drawOrder.length); + let slotCount = skeletonData.slots.length; + let frame = 0; + for (let i = 0; i < map.drawOrder.length; i++, frame++) { + let drawOrderMap = map.drawOrder[i]; + let drawOrder = null; + let offsets = getValue(drawOrderMap, "offsets", null); + if (offsets) { + drawOrder = Utils.newArray(slotCount, -1); + let unchanged = Utils.newArray(slotCount - offsets.length, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsets.length; ii++) { + let offsetMap = offsets[ii]; + let slotIndex = skeletonData.findSlot(offsetMap.slot).index; + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + } + if (map.events) { + let timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + let eventMap = map.events[i]; + let eventData = skeletonData.findEvent(eventMap.name); + let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + event.intValue = getValue(eventMap, "int", eventData.intValue); + event.floatValue = getValue(eventMap, "float", eventData.floatValue); + event.stringValue = getValue(eventMap, "string", eventData.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", 1); + event.balance = getValue(eventMap, "balance", 0); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + skeletonData.animations.push(new Animation(name, timelines, duration)); + } + }; + var LinkedMesh2 = class { + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritDeform = inheritDeform; + } + }; + function readTimeline12(keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value = getValue(keyMap, "value", defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let value2 = getValue(nextMap, "value", defaultValue) * scale; + if (keyMap.curve) + bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + } + function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value1 = getValue(keyMap, name1, defaultValue) * scale; + let value2 = getValue(keyMap, name2, defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; + let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + } + function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve == "stepped") { + timeline.setStepped(frame); + return bezier; + } + let i = value << 2; + let cx1 = curve[i]; + let cy1 = curve[i + 1] * scale; + let cx2 = curve[i + 2]; + let cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; + } + function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; + } + + // spine-core/src/polyfills.ts + (() => { + if (typeof Math.fround === "undefined") { + Math.fround = function(array) { + return function(x) { + return array[0] = x, array[0]; + }; + }(new Float32Array(1)); + } + })(); + + // spine-core/src/vertexeffects/JitterEffect.ts + var JitterEffect = class { + constructor(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; + } + begin(skeleton) { + } + transform(position, uv, light, dark) { + position.x += MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += MathUtils.randomTriangular(-this.jitterX, this.jitterY); + } + end() { + } + }; + + // spine-core/src/vertexeffects/SwirlEffect.ts + var _SwirlEffect = class { + constructor(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; + } + begin(skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + } + transform(position, uv, light, dark) { + let radAngle = this.angle * MathUtils.degreesToRadians; + let x = position.x - this.worldX; + let y = position.y - this.worldY; + let dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + let theta = _SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + let cos = Math.cos(theta); + let sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + } + end() { + } + }; + var SwirlEffect = _SwirlEffect; + SwirlEffect.interpolation = new PowOut(2); + + // spine-canvas/src/CanvasTexture.ts + var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-canvas/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(pathPrefix = "", downloader = null) { + super((image) => { + return new CanvasTexture(image); + }, pathPrefix, downloader); + } + }; + + // spine-canvas/src/SkeletonRenderer.ts + var _SkeletonRenderer = class { + constructor(context) { + this.triangleRendering = false; + this.debugRendering = false; + this.vertices = Utils.newFloatArray(8 * 1024); + this.tempColor = new Color(); + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + } + drawImages(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let bone = slot.bone; + if (!bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof RegionAttachment)) + continue; + let region = attachment.region; + let image = region.page.texture.getImage(); + let slotColor = slot.color; + let regionColor = attachment.color; + color.set(skeletonColor.r * slotColor.r * regionColor.r, skeletonColor.g * slotColor.g * regionColor.g, skeletonColor.b * slotColor.b * regionColor.b, skeletonColor.a * slotColor.a * regionColor.a); + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + let 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; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let attachment = slot.getAttachment(); + let texture; + let region; + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + region = regionAttachment.region; + texture = region.page.texture.getImage(); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.renderObject.page.texture.getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode != blendMode) + blendMode = slot.data.blendMode; + let slotColor = slot.color; + let attachmentColor = attachment.color; + color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, skeletonColor.a * slotColor.a * attachmentColor.a); + 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; + 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]; + this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + let ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = region.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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); + region.computeWorldVertices(slot.bone, this.vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let vertices = this.vertices; + let uvs = region.uvs; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = mesh.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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; + let vertices = this.vertices; + if (vertices.length < mesh.worldVerticesLength) + this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let uvs = mesh.uvs; + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } + }; + var SkeletonRenderer = _SkeletonRenderer; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4; + return src_exports; +})(); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/lib/4.1/spine-canvas.js b/release/MAC版本/lib/4.1/spine-canvas.js new file mode 100644 index 0000000..f2d3b6b --- /dev/null +++ b/release/MAC版本/lib/4.1/spine-canvas.js @@ -0,0 +1,11055 @@ +"use strict"; +var spine = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; + }; + + // spine-canvas/src/index.ts + var src_exports = {}; + __export(src_exports, { + AlphaTimeline: () => AlphaTimeline, + Animation: () => Animation, + AnimationState: () => AnimationState, + AnimationStateAdapter: () => AnimationStateAdapter, + AnimationStateData: () => AnimationStateData, + AssetManager: () => AssetManager, + AssetManagerBase: () => AssetManagerBase, + AtlasAttachmentLoader: () => AtlasAttachmentLoader, + Attachment: () => Attachment, + AttachmentTimeline: () => AttachmentTimeline, + BinaryInput: () => BinaryInput, + BlendMode: () => BlendMode, + Bone: () => Bone, + BoneData: () => BoneData, + BoundingBoxAttachment: () => BoundingBoxAttachment, + CURRENT: () => CURRENT, + CanvasTexture: () => CanvasTexture, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + ConstraintData: () => ConstraintData, + CurveTimeline: () => CurveTimeline, + CurveTimeline1: () => CurveTimeline1, + CurveTimeline2: () => CurveTimeline2, + DebugUtils: () => DebugUtils, + DeformTimeline: () => DeformTimeline, + Downloader: () => Downloader, + DrawOrderTimeline: () => DrawOrderTimeline, + Event: () => Event, + EventData: () => EventData, + EventQueue: () => EventQueue, + EventTimeline: () => EventTimeline, + EventType: () => EventType, + FIRST: () => FIRST, + FakeTexture: () => FakeTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + MathUtils: () => MathUtils, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + PointAttachment: () => PointAttachment, + Pool: () => Pool, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + SequenceTimeline: () => SequenceTimeline, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + StringSet: () => StringSet, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TransformMode: () => TransformMode, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + VertexAttachment: () => VertexAttachment, + WindowedMean: () => WindowedMean + }); + + // spine-core/src/Utils.ts + var IntSet = class { + array = new Array(); + add(value) { + let contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] != void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } + }; + var StringSet = class { + entries = {}; + size = 0; + add(value) { + let contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + let oldSize = this.size; + for (var i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize != this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } + }; + var _Color = class { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) == "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + static fromString(hex) { + return new _Color().setFromString(hex); + } + }; + var Color = _Color; + __publicField(Color, "WHITE", new _Color(1, 1, 1, 1)); + __publicField(Color, "RED", new _Color(1, 0, 0, 1)); + __publicField(Color, "GREEN", new _Color(0, 1, 0, 1)); + __publicField(Color, "BLUE", new _Color(0, 0, 1, 1)); + __publicField(Color, "MAGENTA", new _Color(1, 0, 1, 1)); + var _MathUtils = class { + static clamp(value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + let u = Math.random(); + let d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } + }; + var MathUtils = _MathUtils; + __publicField(MathUtils, "PI", 3.1415927); + __publicField(MathUtils, "PI2", _MathUtils.PI * 2); + __publicField(MathUtils, "radiansToDegrees", 180 / _MathUtils.PI); + __publicField(MathUtils, "radDeg", _MathUtils.radiansToDegrees); + __publicField(MathUtils, "degreesToRadians", _MathUtils.PI / 180); + __publicField(MathUtils, "degRad", _MathUtils.degreesToRadians); + var Interpolation = class { + apply(start, end, a) { + return start + (end - start) * this.applyInternal(a); + } + }; + var Pow = class extends Interpolation { + power = 2; + constructor(power) { + super(); + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + } + }; + var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + } + }; + var _Utils = class { + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + static setArraySize(array, size, value = 0) { + let oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) + array[i] = value; + } + return array; + } + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) + return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + let array = new Array(size); + for (let i = 0; i < size; i++) + array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + // This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109 + static webkit602BugfixHelper(alpha, blend) { + } + static contains(array, element, identity = true) { + for (var i = 0; i < array.length; i++) + if (array[i] == element) + return true; + return false; + } + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } + }; + var Utils = _Utils; + __publicField(Utils, "SUPPORTS_TYPED_ARRAYS", typeof Float32Array !== "undefined"); + var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + let bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + } + }; + var Pool = class { + items = new Array(); + instantiator; + constructor(instantiator) { + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + if (item.reset) + item.reset(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } + }; + var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + let x = this.x; + let y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + let len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + } + }; + var TimeKeeper = class { + maxDelta = 0.064; + framesPerSecond = 0; + delta = 0; + totalTime = 0; + lastTime = Date.now() / 1e3; + frameCount = 0; + frameTime = 0; + update() { + let now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } + }; + var WindowedMean = class { + values; + addedValues = 0; + lastValue = 0; + mean = 0; + dirty = true; + constructor(windowSize = 32) { + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } + }; + + // spine-core/src/attachments/Attachment.ts + var Attachment = class { + name; + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + }; + var _VertexAttachment = class extends Attachment { + /** The unique ID for this attachment. */ + id = _VertexAttachment.nextID++; + /** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting + * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null + * if this attachment has no weights. */ + bones = null; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting + * each vertex. */ + vertices = []; + /** The maximum number of world vertex values that can be output by + * {@link #computeWorldVertices()} using the `count` parameter. */ + worldVerticesLength = 0; + /** Timelines for the timeline attachment are also applied to this attachment. + * May be null if no attachment-specific timelines should be applied. */ + timelineAttachment = this; + constructor(name) { + super(name); + } + /** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is + * not empty, it is used to deform the vertices. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. + * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`. + * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * + * `stride` / 2. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + count = offset + (count >> 1) * stride; + let skeleton = slot.bone.skeleton; + let deformArray = slot.deform; + let vertices = this.vertices; + let bones = this.bones; + if (!bones) { + if (deformArray.length > 0) + vertices = deformArray; + let bone = slot.bone; + let x = bone.worldX; + let y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + let vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices2[w] = vx * a + vy * b + x; + worldVertices2[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + let n = bones[v]; + v += n + 1; + skip += n; + } + let skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } else { + let deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } + } + /** Does not copy id (generated) or name (set on construction). **/ + copyTo(attachment) { + if (this.bones) { + attachment.bones = new Array(this.bones.length); + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + } + }; + var VertexAttachment = _VertexAttachment; + __publicField(VertexAttachment, "nextID", 0); + + // spine-core/src/attachments/Sequence.ts + var _Sequence = class { + id = _Sequence.nextID(); + regions; + start = 0; + digits = 0; + /** The index of the region to show for the setup pose. */ + setupIndex = 0; + constructor(count) { + this.regions = new Array(count); + } + copy() { + let copy = new _Sequence(this.regions.length); + Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length); + copy.start = this.start; + copy.digits = this.digits; + copy.setupIndex = this.setupIndex; + return copy; + } + apply(slot, attachment) { + let index = slot.sequenceIndex; + if (index == -1) + index = this.setupIndex; + if (index >= this.regions.length) + index = this.regions.length - 1; + let region = this.regions[index]; + if (attachment.region != region) { + attachment.region = region; + attachment.updateRegion(); + } + } + getPath(basePath, index) { + let result = basePath; + let frame = (this.start + index).toString(); + for (let i = this.digits - frame.length; i > 0; i--) + result += "0"; + result += frame; + return result; + } + static nextID() { + return _Sequence._nextID++; + } + }; + var Sequence = _Sequence; + __publicField(Sequence, "_nextID", 0); + var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => { + SequenceMode2[SequenceMode2["hold"] = 0] = "hold"; + SequenceMode2[SequenceMode2["once"] = 1] = "once"; + SequenceMode2[SequenceMode2["loop"] = 2] = "loop"; + SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong"; + SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse"; + SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse"; + SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse"; + return SequenceMode2; + })(SequenceMode || {}); + var SequenceModeValues = [ + 0 /* hold */, + 1 /* once */, + 2 /* loop */, + 3 /* pingpong */, + 4 /* onceReverse */, + 5 /* loopReverse */, + 6 /* pingpongReverse */ + ]; + + // spine-core/src/Animation.ts + var Animation = class { + /** The animation's name, which is unique across all animations in the skeleton. */ + name; + timelines = []; + timelineIds = new StringSet(); + /** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */ + duration; + constructor(name, timelines, duration) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + this.setTimelines(timelines); + this.duration = duration; + } + setTimelines(timelines) { + if (!timelines) + throw new Error("timelines cannot be null."); + this.timelines = timelines; + this.timelineIds.clear(); + for (var i = 0; i < timelines.length; i++) + this.timelineIds.addAll(timelines[i].getPropertyIds()); + } + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) + return true; + return false; + } + /** Applies all the animation's timelines to the specified skeleton. + * + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. + * @param loop If true, the animation repeats after {@link #getDuration()}. + * @param events May be null to ignore fired events. */ + apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + let timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + } + }; + var MixBlend = /* @__PURE__ */ ((MixBlend2) => { + MixBlend2[MixBlend2["setup"] = 0] = "setup"; + MixBlend2[MixBlend2["first"] = 1] = "first"; + MixBlend2[MixBlend2["replace"] = 2] = "replace"; + MixBlend2[MixBlend2["add"] = 3] = "add"; + return MixBlend2; + })(MixBlend || {}); + var MixDirection = /* @__PURE__ */ ((MixDirection2) => { + MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn"; + MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut"; + return MixDirection2; + })(MixDirection || {}); + var Property = { + rotate: 0, + x: 1, + y: 2, + scaleX: 3, + scaleY: 4, + shearX: 5, + shearY: 6, + rgb: 7, + alpha: 8, + rgb2: 9, + attachment: 10, + deform: 11, + event: 12, + drawOrder: 13, + ikConstraint: 14, + transformConstraint: 15, + pathConstraintPosition: 16, + pathConstraintSpacing: 17, + pathConstraintMix: 18, + sequence: 19 + }; + var Timeline = class { + propertyIds; + frames; + constructor(frameCount, propertyIds) { + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + getFrameEntries() { + return 1; + } + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + static search1(frames, time) { + let n = frames.length; + for (let i = 1; i < n; i++) + if (frames[i] > time) + return i - 1; + return n - 1; + } + static search(frames, time, step) { + let n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) + return i - step; + return n - step; + } + }; + var CurveTimeline = class extends Timeline { + curves; + // type, x, y, ... + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + this.curves = Utils.newFloatArray( + frameCount + bezierCount * 18 + /*BEZIER_SIZE*/ + ); + this.curves[frameCount - 1] = 1; + } + /** Sets the specified key frame to linear interpolation. */ + setLinear(frame) { + this.curves[frame] = 0; + } + /** Sets the specified key frame to stepped interpolation. */ + setStepped(frame) { + this.curves[frame] = 1; + } + /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger + * than the actual number of Bezier curves. */ + shrink(bezierCount) { + let size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + let newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than + * one curve per frame. + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified + * in the constructor), inclusive. + * @param frame Between 0 and frameCount - 1, inclusive. + * @param value The index of the value for this frame that this curve is used for. + * @param time1 The time for the first key. + * @param value1 The value for the first key. + * @param cx1 The time for the first Bezier handle. + * @param cy1 The value for the first Bezier handle. + * @param cx2 The time of the second Bezier handle. + * @param cy2 The value for the second Bezier handle. + * @param time2 The time for the second key. + * @param value2 The value for the second key. */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + /** Returns the Bezier interpolated value for the specified time. + * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time. + * @param valueOffset The offset from frameIndex to the value this curve is used for. + * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ + getBezierValue(time, frameIndex, valueOffset, i) { + let curves = this.curves; + if (curves[i] > time) { + let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + let x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } + }; + var CurveTimeline1 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, [propertyId]); + } + getFrameEntries() { + return 2; + } + /** Sets the time and value for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE*/ + ] = value; + } + /** Returns the interpolated value for the specified time. */ + getCurveValue(time) { + let frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + let curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: + let before = frames[i], value = frames[ + i + 1 + /*VALUE*/ + ]; + return value + (time - before) / (frames[ + i + 2 + /*ENTRIES*/ + ] - before) * (frames[ + i + 2 + 1 + /*VALUE*/ + ] - value); + case 1: + return frames[ + i + 1 + /*VALUE*/ + ]; + } + return this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + } + }; + var CurveTimeline2 = class extends CurveTimeline { + /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + constructor(frameCount, bezierCount, propertyId1, propertyId2) { + super(frameCount, bezierCount, [propertyId1, propertyId2]); + } + getFrameEntries() { + return 3; + } + /** Sets the time and values for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE1*/ + ] = value1; + this.frames[ + frame + 2 + /*VALUE2*/ + ] = value2; + } + }; + var RotateTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.rotate + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation; + return; + case 1 /* first */: + bone.rotation += (bone.data.rotation - bone.rotation) * alpha; + } + return; + } + let r = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation + r * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + r += bone.data.rotation - bone.rotation; + case 3 /* add */: + bone.rotation += r * alpha; + } + } + }; + var TranslateTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.x + "|" + boneIndex, + Property.y + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case 1 /* first */: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3 /* add */: + bone.x += x * alpha; + bone.y += y * alpha; + } + } + }; + var TranslateXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x; + return; + case 1 /* first */: + bone.x += (bone.data.x - bone.x) * alpha; + } + return; + } + let x = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x + x * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.x += (bone.data.x + x - bone.x) * alpha; + break; + case 3 /* add */: + bone.x += x * alpha; + } + } + }; + var TranslateYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.y + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.y = bone.data.y; + return; + case 1 /* first */: + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let y = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + bone.y = bone.data.y + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3 /* add */: + bone.y += y * alpha; + } + } + }; + var ScaleTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.scaleX + "|" + boneIndex, + Property.scaleY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case 1 /* first */: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let x, y; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + x *= bone.data.scaleX; + y *= bone.data.scaleY; + if (alpha == 1) { + if (blend == 3 /* add */) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } else { + bone.scaleX = x; + bone.scaleY = y; + } + } else { + let bx = 0, by = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ScaleXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleX = bone.data.scaleX; + return; + case 1 /* first */: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + } + return; + } + let x = this.getCurveValue(time) * bone.data.scaleX; + if (alpha == 1) { + if (blend == 3 /* add */) + bone.scaleX += x - bone.data.scaleX; + else + bone.scaleX = x; + } else { + let bx = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + bx = bone.data.scaleX; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = bone.scaleX; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + bone.scaleX = bx + (x - bx) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + bone.scaleX = bx + (x - bx) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + } + } + } + } + }; + var ScaleYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleY = bone.data.scaleY; + return; + case 1 /* first */: + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let y = this.getCurveValue(time) * bone.data.scaleY; + if (alpha == 1) { + if (blend == 3 /* add */) + bone.scaleY += y - bone.data.scaleY; + else + bone.scaleY = y; + } else { + let by = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + by = bone.data.scaleY; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + by = bone.scaleY; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3 /* add */: + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleY = by + (y - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleY = by + (y - by) * alpha; + break; + case 3 /* add */: + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ShearTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.shearX + "|" + boneIndex, + Property.shearY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case 1 /* first */: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3 /* add */: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + } + }; + var ShearXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX; + return; + case 1 /* first */: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + } + return; + } + let x = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX + x * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + break; + case 3 /* add */: + bone.shearX += x * alpha; + } + } + }; + var ShearYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearY = bone.data.shearY; + return; + case 1 /* first */: + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let y = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3 /* add */: + bone.shearY += y * alpha; + } + } + }; + var RGBATimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 5; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.setFromColor(setup); + return; + case 1 /* first */: + color.add( + (setup.r - color.r) * alpha, + (setup.g - color.g) * alpha, + (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha + ); + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + let i = Timeline.search( + frames, + time, + 5 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 5 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + let t = (time - before) / (frames[ + i + 5 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 5 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 5 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 5 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 5 + 4 + /*A*/ + ] - a) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == 0 /* setup */) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } + }; + var RGBTimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 4; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + return; + case 1 /* first */: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 4 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 4 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 4 + 3 + /*B*/ + ] - b) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + color.r = r; + color.g = g; + color.b = b; + } else { + if (blend == 0 /* setup */) { + let setup = slot.data.color; + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + } + color.r += (r - color.r) * alpha; + color.g += (g - color.g) * alpha; + color.b += (b - color.b) * alpha; + } + } + }; + var AlphaTimeline = class extends CurveTimeline1 { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let color = slot.color; + if (time < this.frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.a = setup.a; + return; + case 1 /* first */: + color.a += (setup.a - color.a) * alpha; + } + return; + } + let a = this.getCurveValue(time); + if (alpha == 1) + color.a = a; + else { + if (blend == 0 /* setup */) + color.a = slot.data.color.a; + color.a += (a - color.a) * alpha; + } + } + }; + var RGBA2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 8; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + this.frames[ + frame + 5 + /*R2*/ + ] = r2; + this.frames[ + frame + 6 + /*G2*/ + ] = g2; + this.frames[ + frame + 7 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.add( + (setupLight.r - light.r) * alpha, + (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha + ); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 8 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 8 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 8 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 8 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 8 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 8 + 4 + /*A*/ + ] - a) * t; + r2 += (frames[ + i + 8 + 5 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 8 + 6 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 8 + 7 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 7, + curveType + 18 * 6 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.set(r, g, b, a); + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + light.setFromColor(slot.data.color); + let setupDark = slot.data.darkColor; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var RGB2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 7; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*R2*/ + ] = r2; + this.frames[ + frame + 5 + /*G2*/ + ] = g2; + this.frames[ + frame + 6 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 7 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 7 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 7 + 3 + /*B*/ + ] - b) * t; + r2 += (frames[ + i + 7 + 4 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 7 + 5 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 7 + 6 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.r = r; + light.g = g; + light.b = b; + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.r += (r - light.r) * alpha; + light.g += (g - light.g) * alpha; + light.b += (b - light.b) * alpha; + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var AttachmentTimeline = class extends Timeline { + slotIndex = 0; + /** The attachment name for each key frame. May contain null values to clear the attachment. */ + attachmentNames; + constructor(frameCount, slotIndex) { + super(frameCount, [ + Property.attachment + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the attachment name for the specified key frame. */ + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]); + } + setAttachment(skeleton, slot, attachmentName) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } + }; + var DeformTimeline = class extends CurveTimeline { + slotIndex = 0; + /** The attachment that will be deformed. */ + attachment; + /** The vertices for each key frame. */ + vertices; + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, [ + Property.deform + "|" + slotIndex + "|" + attachment.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the vertices for the specified key frame. + * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + /** @param value1 Ignored (0 is used for a deform timeline). + * @param value2 Ignored (1 is used for a deform timeline). */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + let curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: + let x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + let x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + let x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.getAttachment(); + if (!slotAttachment) + return; + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment) + return; + let deform = slot.deform; + if (deform.length == 0) + blend = 0 /* setup */; + let vertices = this.vertices; + let vertexCount = vertices[0].length; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + deform.length = 0; + return; + case 1 /* first */: + if (alpha == 1) { + deform.length = 0; + return; + } + deform.length = vertexCount; + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + return; + } + deform.length = vertexCount; + if (time >= frames[frames.length - 1]) { + let lastVertices = vertices[frames.length - 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] - setupVertices[i2]; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2]; + } + } else + Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let setup = setupVertices[i2]; + deform[i2] = setup + (lastVertices[i2] - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] = lastVertices[i2] * alpha; + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - deform[i2]) * alpha; + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] * alpha; + } + } + } + return; + } + let frame = Timeline.search1(frames, time); + let percent = this.getCurvePercent(time, frame); + let prevVertices = vertices[frame]; + let nextVertices = vertices[frame + 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2], setup = setupVertices[i2]; + deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha; + } + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + } + } + } + }; + var _EventTimeline = class extends Timeline { + /** The event for each key frame. */ + events; + constructor(frameCount) { + super(frameCount, _EventTimeline.propertyIds); + this.events = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the event for the specified key frame. */ + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + /** Fires events for frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (!firedEvents) + return; + let frames = this.frames; + let frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search1(frames, lastTime) + 1; + let frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] != frameTime) + break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } + }; + var EventTimeline = _EventTimeline; + __publicField(EventTimeline, "propertyIds", ["" + Property.event]); + var _DrawOrderTimeline = class extends Timeline { + /** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */ + drawOrders; + constructor(frameCount) { + super(frameCount, _DrawOrderTimeline.propertyIds); + this.drawOrders = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the draw order for the specified key frame. + * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose + * draw order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + let idx = Timeline.search1(this.frames, time); + let drawOrderToSetupIndex = this.drawOrders[idx]; + if (!drawOrderToSetupIndex) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + else { + let drawOrder = skeleton.drawOrder; + let slots = skeleton.slots; + for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } + }; + var DrawOrderTimeline = _DrawOrderTimeline; + __publicField(DrawOrderTimeline, "propertyIds", ["" + Property.drawOrder]); + var IkConstraintTimeline = class extends CurveTimeline { + /** The index of the IK constraint slot in {@link Skeleton#ikConstraints} that will be changed. */ + ikConstraintIndex = 0; + constructor(frameCount, bezierCount, ikConstraintIndex) { + super(frameCount, bezierCount, [ + Property.ikConstraint + "|" + ikConstraintIndex + ]); + this.ikConstraintIndex = ikConstraintIndex; + } + getFrameEntries() { + return 6; + } + /** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */ + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*MIX*/ + ] = mix; + this.frames[ + frame + 2 + /*SOFTNESS*/ + ] = softness; + this.frames[ + frame + 3 + /*BEND_DIRECTION*/ + ] = bendDirection; + this.frames[ + frame + 4 + /*COMPRESS*/ + ] = compress ? 1 : 0; + this.frames[ + frame + 5 + /*STRETCH*/ + ] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.ikConstraints[this.ikConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case 1 /* first */: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + let mix = 0, softness = 0; + let i = Timeline.search( + frames, + time, + 6 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 6 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + let t = (time - before) / (frames[ + i + 6 + /*ENTRIES*/ + ] - before); + mix += (frames[ + i + 6 + 1 + /*MIX*/ + ] - mix) * t; + softness += (frames[ + i + 6 + 2 + /*SOFTNESS*/ + ] - softness) * t; + break; + case 1: + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + break; + default: + mix = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + softness = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (direction == 1 /* mixOut */) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } else { + constraint.mix += (mix - constraint.mix) * alpha; + constraint.softness += (softness - constraint.softness) * alpha; + if (direction == 0 /* mixIn */) { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } + } + }; + var TransformConstraintTimeline = class extends CurveTimeline { + /** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */ + transformConstraintIndex = 0; + constructor(frameCount, bezierCount, transformConstraintIndex) { + super(frameCount, bezierCount, [ + Property.transformConstraint + "|" + transformConstraintIndex + ]); + this.transformConstraintIndex = transformConstraintIndex; + } + getFrameEntries() { + return 7; + } + /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */ + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + let frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + frames[ + frame + 4 + /*SCALEX*/ + ] = mixScaleX; + frames[ + frame + 5 + /*SCALEY*/ + ] = mixScaleY; + frames[ + frame + 6 + /*SHEARY*/ + ] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.transformConstraints[this.transformConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + let data = constraint.data; + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + return; + case 1 /* first */: + constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (data.mixX - constraint.mixX) * alpha; + constraint.mixY += (data.mixY - constraint.mixY) * alpha; + constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 7 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 7 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 7 + 3 + /*Y*/ + ] - y) * t; + scaleX += (frames[ + i + 7 + 4 + /*SCALEX*/ + ] - scaleX) * t; + scaleY += (frames[ + i + 7 + 5 + /*SCALEY*/ + ] - scaleY) * t; + shearY += (frames[ + i + 7 + 6 + /*SHEARY*/ + ] - shearY) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + scaleX = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + scaleY = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + shearY = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; + constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; + constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + } + } + }; + var PathConstraintPositionTimeline = class extends CurveTimeline1 { + /** The index of the path constraint slot in {@link Skeleton#pathConstraints} that will be changed. */ + pathConstraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex); + this.pathConstraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.position = constraint.data.position; + return; + case 1 /* first */: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } + return; + } + let position = this.getCurveValue(time); + if (blend == 0 /* setup */) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + } + }; + var PathConstraintSpacingTimeline = class extends CurveTimeline1 { + /** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */ + pathConstraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex); + this.pathConstraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.spacing = constraint.data.spacing; + return; + case 1 /* first */: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } + return; + } + let spacing = this.getCurveValue(time); + if (blend == 0 /* setup */) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + } + }; + var PathConstraintMixTimeline = class extends CurveTimeline { + /** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */ + pathConstraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, [ + Property.pathConstraintMix + "|" + pathConstraintIndex + ]); + this.pathConstraintIndex = pathConstraintIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, mixRotate, mixX, mixY) { + let frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.pathConstraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = constraint.data.mixRotate; + constraint.mixX = constraint.data.mixX; + constraint.mixY = constraint.data.mixY; + return; + case 1 /* first */: + constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha; + constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha; + } + return; + } + let rotate, x, y; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 4 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 4 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 4 + 3 + /*Y*/ + ] - y) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + } + } + }; + var _SequenceTimeline = class extends Timeline { + slotIndex; + attachment; + constructor(frameCount, slotIndex, attachment) { + super(frameCount, [ + Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + } + getFrameEntries() { + return _SequenceTimeline.ENTRIES; + } + getSlotIndex() { + return this.slotIndex; + } + getAttachment() { + return this.attachment; + } + /** Sets the time, mode, index, and frame time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time Seconds between frames. */ + setFrame(frame, time, mode, index, delay) { + let frames = this.frames; + frame *= _SequenceTimeline.ENTRIES; + frames[frame] = time; + frames[frame + _SequenceTimeline.MODE] = mode | index << 4; + frames[frame + _SequenceTimeline.DELAY] = delay; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.attachment; + let attachment = this.attachment; + if (slotAttachment != attachment) { + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment) + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + slot.sequenceIndex = -1; + return; + } + let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES); + let before = frames[i]; + let modeAndIndex = frames[i + _SequenceTimeline.MODE]; + let delay = frames[i + _SequenceTimeline.DELAY]; + if (!this.attachment.sequence) + return; + let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length; + let mode = SequenceModeValues[modeAndIndex & 15]; + if (mode != 0 /* hold */) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case 1 /* once */: + index = Math.min(count - 1, index); + break; + case 2 /* loop */: + index %= count; + break; + case 3 /* pingpong */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) + index = n - index; + break; + } + case 4 /* onceReverse */: + index = Math.max(count - 1 - index, 0); + break; + case 5 /* loopReverse */: + index = count - 1 - index % count; + break; + case 6 /* pingpongReverse */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) + index = n - index; + } + } + } + slot.sequenceIndex = index; + } + }; + var SequenceTimeline = _SequenceTimeline; + __publicField(SequenceTimeline, "ENTRIES", 3); + __publicField(SequenceTimeline, "MODE", 1); + __publicField(SequenceTimeline, "DELAY", 2); + + // spine-core/src/AnimationState.ts + var _AnimationState = class { + static emptyAnimation() { + return _AnimationState._emptyAnimation; + } + /** The AnimationStateData to look up mix durations. */ + data; + /** The list of tracks that currently have animations, which may contain null entries. */ + tracks = new Array(); + /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + * or faster. Defaults to 1. + * + * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */ + timeScale = 1; + unkeyedState = 0; + events = new Array(); + listeners = new Array(); + queue = new EventQueue(this); + propertyIDs = new StringSet(); + animationsChanged = false; + trackEntryPool = new Pool(() => new TrackEntry()); + constructor(data) { + this.data = data; + } + /** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */ + update(delta) { + delta *= this.timeScale; + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let current = tracks[i]; + if (!current) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + let nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) + from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + /** Returns true when all mixing from entries are complete. */ + updateMixingFrom(to, delta) { + let from = to.mixingFrom; + if (!from) + return true; + let finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + /** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + * animation state can be applied to multiple skeletons to pose them identically. + * @returns True if any animations were applied. */ + apply(skeleton) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + let events = this.events; + let tracks = this.tracks; + let applied = false; + for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) { + let current = tracks[i2]; + if (!current || current.delay > 0) + continue; + applied = true; + let blend = i2 == 0 ? 1 /* first */ : current.mixBlend; + let mix = current.alpha; + if (current.mixingFrom) + mix *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && !current.next) + mix = 0; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + let timelines = current.animation.timelines; + let timelineCount = timelines.length; + if (i2 == 0 && mix == 1 || blend == 3 /* add */) { + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(mix, blend); + var timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, true); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, 0 /* mixIn */); + } + } else { + let timelineMode = current.timelineMode; + let shortestRotation = current.shortestRotation; + let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + let timeline2 = timelines[ii]; + let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */; + if (!shortestRotation && timeline2 instanceof RotateTimeline) { + this.applyRotateTimeline(timeline2, skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline2 instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, true); + } else { + Utils.webkit602BugfixHelper(mix, blend); + timeline2.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, 0 /* mixIn */); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton, blend) { + let from = to.mixingFrom; + if (from.mixingFrom) + this.applyMixingFrom(from, skeleton, blend); + let mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == 1 /* first */) + blend = 0 /* setup */; + } else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != 1 /* first */) + blend = from.mixBlend; + } + let attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; + let timelines = from.animation.timelines; + let timelineCount = timelines.length; + let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + if (blend == 3 /* add */) { + for (let i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */); + } else { + let timelineMode = from.timelineMode; + let timelineHoldMix = from.timelineHoldMix; + let shortestRotation = from.shortestRotation; + let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + from.timelinesRotation.length = timelineCount << 1; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + let timeline = timelines[i]; + let direction = 1 /* mixOut */; + let timelineBlend; + let alpha = 0; + switch (timelineMode[i]) { + case SUBSEQUENT: + if (!drawOrder && timeline instanceof DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaMix; + break; + case HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case HOLD_FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaHold; + break; + default: + timelineBlend = 0 /* setup */; + let holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (!shortestRotation && timeline instanceof RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments); + else { + Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */) + direction = 0 /* mixIn */; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) + return; + if (time < timeline.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } else + this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments); + if (slot.attachmentState <= this.unkeyedState) + slot.attachmentState = this.unkeyedState + SETUP; + } + setAttachment(skeleton, slot, attachmentName, attachments) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) + slot.attachmentState = this.unkeyedState + CURRENT; + } + applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */); + return; + } + let bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) + return; + let frames = timeline.frames; + let r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation; + default: + return; + case 1 /* first */: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } else { + r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation; + r2 = bone.data.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= (16384 - (16384.499999999996 - diff / 360 | 0)) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + let current = diff > 0, dir = lastTotal >= 0; + if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) { + if (Math.abs(lastTotal) > 180) + lastTotal += 360 * MathUtils.signum(lastTotal); + dir = current; + } + total = diff + lastTotal - lastTotal % 360; + if (dir != current) + total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + let animationStart = entry.animationStart, animationEnd = entry.animationEnd; + let duration = animationEnd - animationStart; + let trackLastWrapped = entry.trackLast % duration; + let events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + let event = events[i]; + if (event.time < trackLastWrapped) + break; + if (event.time > animationEnd) + continue; + this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + let event = events[i]; + if (event.time < animationStart) + continue; + this.queue.event(entry, event); + } + } + /** Removes all animations from all tracks, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTracks() { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + /** Removes all animations from the track, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTrack(trackIndex) { + if (trackIndex >= this.tracks.length) + return; + let current = this.tracks[trackIndex]; + if (!current) + return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + let from = entry.mixingFrom; + if (!from) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setCurrent(index, current, interrupt) { + let from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + /** Sets an animation by name. + * + * See {@link #setAnimationWith()}. */ + setAnimation(trackIndex, animationName, loop = false) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + } + /** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never + * applied to a skeleton, it is replaced (not mixed from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + setAnimationWith(trackIndex, animation, loop = false) { + if (!animation) + throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + let entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + /** Queues an animation by name. + * + * See {@link #addAnimationWith()}. */ + addAnimation(trackIndex, animationName, loop = false, delay = 0) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + } + /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is + * equivalent to calling {@link #setAnimationWith()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix + * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the + * previous entry is looping, its next loop completion is used instead of its duration. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addAnimationWith(trackIndex, animation, loop = false, delay = 0) { + if (!animation) + throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + let entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) + delay += last.getTrackComplete() - entry.mixDuration; + } + entry.delay = delay; + return entry; + } + /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()}, + * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still mixes out over one frame. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * {@link #addAnimation()} and on the returned track entry, set the + * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and + * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the + * setup pose value if no lower tracks key the property to the value keyed in the new animation. */ + setEmptyAnimation(trackIndex, mixDuration = 0) { + let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling + * {@link #setEmptyAnimation()}. + * + * See {@link #setEmptyAnimation()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or + * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next + * loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay); + if (delay <= 0) + entry.delay += entry.mixDuration - mixDuration; + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix + * duration. */ + setEmptyAnimations(mixDuration = 0) { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + let current = this.tracks[i]; + if (current) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) + return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + /** @param last May be null. */ + trackEntry(trackIndex, animation, loop, last) { + let entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.reverse = false; + entry.shortestRotation = false; + entry.eventThreshold = 0; + entry.attachmentThreshold = 0; + entry.drawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.interruptAlpha = 1; + entry.totalAlpha = 0; + entry.mixBlend = 2 /* replace */; + return entry; + } + /** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */ + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + this.propertyIDs.clear(); + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let entry = tracks[i]; + if (!entry) + continue; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + if (!entry.mixingTo || entry.mixBlend != 3 /* add */) + this.computeHold(entry); + entry = entry.mixingTo; + } while (entry); + } + } + computeHold(entry) { + let to = entry.mixingTo; + let timelines = entry.animation.timelines; + let timelinesCount = entry.animation.timelines.length; + let timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + let timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + let propertyIDs = this.propertyIDs; + if (to && to.holdPrevious) { + for (let i = 0; i < timelinesCount; i++) + timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; + return; + } + outer: + for (let i = 0; i < timelinesCount; i++) { + let timeline = timelines[i]; + let ids = timeline.getPropertyIds(); + if (!propertyIDs.addAll(ids)) + timelineMode[i] = SUBSEQUENT; + else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) { + timelineMode[i] = FIRST; + } else { + for (let next = to.mixingTo; next; next = next.mixingTo) { + if (next.animation.hasTimeline(ids)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = HOLD_MIX; + timelineHoldMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = HOLD_FIRST; + } + } + } + /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */ + getCurrent(trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + } + /** Adds a listener to receive events for all track entries. */ + addListener(listener) { + if (!listener) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + /** Removes the listener added with {@link #addListener()}. */ + removeListener(listener) { + let index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + } + /** Removes all listeners added with {@link #addListener()}. */ + clearListeners() { + this.listeners.length = 0; + } + /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. */ + clearListenerNotifications() { + this.queue.clear(); + } + }; + var AnimationState = _AnimationState; + __publicField(AnimationState, "_emptyAnimation", new Animation("", [], 0)); + var TrackEntry = class { + /** The animation to apply for this track entry. */ + animation = null; + previous = null; + /** The animation queued to start after this animation, or null. `next` makes up a linked list. */ + next = null; + /** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */ + mixingFrom = null; + /** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is + * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */ + mixingTo = null; + /** The listener for events generated by this track entry, or null. + * + * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation + * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */ + listener = null; + /** The index of the track where this track entry is either current or queued. + * + * See {@link AnimationState#getCurrent()}. */ + trackIndex = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ + loop = false; + /** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + * of being mixed out. + * + * When mixing between animations that key the same property, if a lower track also keys that property then the value will + * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation + * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + * keys the property, only when a higher track also keys the property. + * + * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the + * previous animation. */ + holdPrevious = false; + reverse = false; + shortestRotation = false; + /** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the + * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event + * timelines are not applied while this animation is being mixed out. */ + eventThreshold = 0; + /** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the + * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to + * 0, so attachment timelines are not applied while this animation is being mixed out. */ + attachmentThreshold = 0; + /** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the + * `drawOrderThreshold`, draw order timelines are applied while this animation is being mixed out. Defaults to 0, + * so draw order timelines are not applied while this animation is being mixed out. */ + drawOrderThreshold = 0; + /** Seconds when this animation starts, both initially and after looping. Defaults to 0. + * + * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same + * value to prevent timeline keys before the start time from triggering. */ + animationStart = 0; + /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */ + animationEnd = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and + * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation + * is applied. */ + animationLast = 0; + nextAnimationLast = 0; + /** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay` + * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from + * the start of the previous animation to when this track entry will become the current track entry (ie when the previous + * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`). + * + * {@link #timeScale} affects the delay. */ + delay = 0; + /** Current time in seconds this track entry has been the current track entry. The track time determines + * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting + * looping. */ + trackTime = 0; + trackLast = 0; + nextTrackLast = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation + * abruptly cease being applied. */ + trackEnd = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to + * match the animation speed. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If + * the time scale is not 1, the delay may need to be adjusted. + * + * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */ + timeScale = 0; + /** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults + * to 1, which overwrites the skeleton's current pose with this animation. + * + * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to + * use alpha on track 0 if the skeleton pose is from the last frame render. */ + alpha = 0; + /** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be + * slightly more than `mixDuration` when the mix is complete. */ + mixTime = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData + * {@link AnimationStateData#getMix()} based on the animation before this animation (if any). + * + * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the + * properties it was animating. + * + * The `mixDuration` can be set manually rather than use the value from + * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new + * track entry only before {@link AnimationState#update(float)} is first called. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set + * afterward. */ + mixDuration = 0; + interruptAlpha = 0; + totalAlpha = 0; + /** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which + * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to + * the values from the lower tracks. + * + * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first + * called. */ + mixBlend = 2 /* replace */; + timelineMode = new Array(); + timelineHoldMix = new Array(); + timelinesRotation = new Array(); + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + /** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart} + * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the + * `animationStart` time. */ + getAnimationTime() { + if (this.loop) { + let duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + /** Returns true if at least one loop has been completed. + * + * See {@link AnimationStateListener#complete()}. */ + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + /** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + * long way around when using {@link #alpha} and starting animations on other tracks. + * + * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions: + * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long + * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the + * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */ + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + getTrackComplete() { + let duration = this.animationEnd - this.animationStart; + if (duration != 0) { + if (this.loop) + return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) + return duration; + } + return this.trackTime; + } + }; + var EventQueue = class { + objects = []; + drainDisabled = false; + animState; + constructor(animState) { + this.animState = animState; + } + start(entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + } + end(entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) + return; + this.drainDisabled = true; + let objects = this.objects; + let listeners = this.animState.listeners; + for (let i = 0; i < objects.length; i += 2) { + let type = objects[i]; + let entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener && entry.listener.start) + entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.start) + listener.start(entry); + } + break; + case EventType.interrupt: + if (entry.listener && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.interrupt) + listener.interrupt(entry); + } + break; + case EventType.end: + if (entry.listener && entry.listener.end) + entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.end) + listener.end(entry); + } + case EventType.dispose: + if (entry.listener && entry.listener.dispose) + entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.dispose) + listener.dispose(entry); + } + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener && entry.listener.complete) + entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.complete) + listener.complete(entry); + } + break; + case EventType.event: + let event = objects[i++ + 2]; + if (entry.listener && entry.listener.event) + entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.event) + listener.event(entry, event); + } + break; + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } + }; + var EventType = /* @__PURE__ */ ((EventType2) => { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + return EventType2; + })(EventType || {}); + var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } + }; + var SUBSEQUENT = 0; + var FIRST = 1; + var HOLD_SUBSEQUENT = 2; + var HOLD_FIRST = 3; + var HOLD_MIX = 4; + var SETUP = 1; + var CURRENT = 2; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + /** The SkeletonData to look up animations when they are specified by name. */ + skeletonData; + animationToMixTime = {}; + /** The mix duration to use when no mix duration has been defined between two animations. */ + defaultMix = 0; + constructor(skeletonData) { + if (!skeletonData) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + /** Sets a mix duration by animation name. + * + * See {@link #setMixWith()}. */ + setMix(fromName, toName, duration) { + let from = this.skeletonData.findAnimation(fromName); + if (!from) + throw new Error("Animation not found: " + fromName); + let to = this.skeletonData.findAnimation(toName); + if (!to) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + } + /** Sets the mix duration when changing from the specified animation to the other. + * + * See {@link TrackEntry#mixDuration}. */ + setMixWith(from, to, duration) { + if (!from) + throw new Error("from cannot be null."); + if (!to) + throw new Error("to cannot be null."); + let key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + } + /** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if + * no mix duration has been set. */ + getMix(from, to) { + let key = from.name + "." + to.name; + let value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } + }; + + // spine-core/src/attachments/BoundingBoxAttachment.ts + var BoundingBoxAttachment = class extends VertexAttachment { + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/ClippingAttachment.ts + var ClippingAttachment = class extends VertexAttachment { + /** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of + * the skeleton's rendering. */ + endSlot = null; + // Nonessential. + /** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons + * are not usually rendered at runtime. */ + color = new Color(0.2275, 0.2275, 0.8078, 1); + // ce3a3aff + constructor(name) { + super(name); + } + copy() { + let copy = new ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/Texture.ts + var Texture = class { + _image; + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } + }; + var TextureFilter = /* @__PURE__ */ ((TextureFilter3) => { + TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest"; + TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear"; + TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap"; + TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + return TextureFilter3; + })(TextureFilter || {}); + var TextureWrap = /* @__PURE__ */ ((TextureWrap3) => { + TextureWrap3[TextureWrap3["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap3[TextureWrap3["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap3[TextureWrap3["Repeat"] = 10497] = "Repeat"; + return TextureWrap3; + })(TextureWrap || {}); + var TextureRegion = class { + texture; + u = 0; + v = 0; + u2 = 0; + v2 = 0; + width = 0; + height = 0; + degrees = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + }; + var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-core/src/TextureAtlas.ts + var TextureAtlas = class { + pages = new Array(); + regions = new Array(); + constructor(atlasText) { + let reader = new TextureAtlasReader(atlasText); + let entry = new Array(4); + let pageFields = {}; + pageFields["size"] = (page2) => { + page2.width = parseInt(entry[1]); + page2.height = parseInt(entry[2]); + }; + pageFields["format"] = () => { + }; + pageFields["filter"] = (page2) => { + page2.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page2.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields["repeat"] = (page2) => { + if (entry[1].indexOf("x") != -1) + page2.uWrap = 10497 /* Repeat */; + if (entry[1].indexOf("y") != -1) + page2.vWrap = 10497 /* Repeat */; + }; + pageFields["pma"] = (page2) => { + page2.pma = entry[1] == "true"; + }; + var regionFields = {}; + regionFields["xy"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields["size"] = (region) => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields["bounds"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields["offset"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields["orig"] = (region) => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields["offsets"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields["rotate"] = (region) => { + let value = entry[1]; + if (value == "true") + region.degrees = 90; + else if (value != "false") + region.degrees = parseInt(value); + }; + regionFields["index"] = (region) => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length == 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length == 0) + break; + if (reader.readEntry(entry, line) == 0) + break; + line = reader.readLine(); + } + let page = null; + let names = null; + let values = null; + while (true) { + if (line === null) + break; + if (line.trim().length == 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(line.trim()); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) == 0) + break; + let field = pageFields[entry[0]]; + if (field) + field(page); + } + this.pages.push(page); + } else { + let region = new TextureAtlasRegion(page, line); + while (true) { + let count = reader.readEntry(entry, line = reader.readLine()); + if (count == 0) + break; + let field = regionFields[entry[0]]; + if (field) + field(region); + else { + if (!names) + names = []; + if (!values) + values = []; + names.push(entry[0]); + let entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth == 0 && region.originalHeight == 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0 && values && values.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees == 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (let page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture?.dispose(); + } + } + }; + var TextureAtlasReader = class { + lines; + index = 0; + constructor(text) { + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) + return 0; + line = line.trim(); + if (line.length == 0) + return 0; + let colon = line.indexOf(":"); + if (colon == -1) + return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + let comma = line.indexOf(",", lastMatch); + if (comma == -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) + return 4; + } + } + }; + var TextureAtlasPage = class { + name; + minFilter = 9728 /* Nearest */; + magFilter = 9728 /* Nearest */; + uWrap = 33071 /* ClampToEdge */; + vWrap = 33071 /* ClampToEdge */; + texture = null; + width = 0; + height = 0; + pma = false; + regions = new Array(); + constructor(name) { + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + for (let region of this.regions) + region.texture = texture; + } + }; + var TextureAtlasRegion = class extends TextureRegion { + page; + name; + x = 0; + y = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + index = 0; + degrees = 0; + names = null; + values = null; + constructor(page, name) { + super(); + this.page = page; + this.name = name; + page.regions.push(this); + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class extends VertexAttachment { + region = null; + /** The name of the texture region for this attachment. */ + path; + /** The UV pair for each vertex, normalized within the texture region. */ + regionUVs = []; + /** The UV pair for each vertex, normalized within the entire texture. + * + * See {@link #updateUVs}. */ + uvs = []; + /** Triplets of vertex indices which describe the mesh's triangulation. */ + triangles = []; + /** The color to tint the mesh. */ + color = new Color(1, 1, 1, 1); + /** The width of the mesh's image. Available only when nonessential data was exported. */ + width = 0; + /** The height of the mesh's image. Available only when nonessential data was exported. */ + height = 0; + /** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */ + hullLength = 0; + /** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if + * nonessential data was exported. Triangulation is not performed at runtime. */ + edges = []; + parentMesh = null; + sequence = null; + tempColor = new Color(0, 0, 0, 0); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or + * the {@link #regionUVs} are changed. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length != regionUVs.length) + this.uvs = Utils.newFloatArray(regionUVs.length); + let uvs = this.uvs; + let n = this.uvs.length; + let u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof TextureAtlasRegion) { + let region = this.region, image = region.page.texture.getImage(); + let textureWidth = image.width, textureHeight = image.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } else if (!this.region) { + u = v = 0; + width = height = 1; + } else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices}, + * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the + * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */ + getParentMesh() { + return this.parentMesh; + } + /** @param parentMesh May be null. */ + setParentMesh(parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + } + copy() { + if (this.parentMesh) + return this.newLinkedMesh(); + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = new Array(this.uvs.length); + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + if (this.edges) { + copy.edges = new Array(this.edges.length); + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices2, offset, stride); + } + /** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/ + newLinkedMesh() { + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + copy.timelineAttachment = this.timelineAttachment; + copy.setParentMesh(this.parentMesh ? this.parentMesh : this); + if (copy.region != null) + copy.updateRegion(); + return copy; + } + }; + + // spine-core/src/attachments/PathAttachment.ts + var PathAttachment = class extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ + lengths = []; + /** If true, the start and end knots are connected. */ + closed = false; + /** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer + * calculations are performed but calculating positions along the path is less accurate. */ + constantSpeed = false; + /** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually + * rendered at runtime. */ + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PointAttachment.ts + var PointAttachment = class extends VertexAttachment { + x = 0; + y = 0; + rotation = 0; + /** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments + * are not usually rendered at runtime. */ + color = new Color(0.38, 0.94, 0, 1); + constructor(name) { + super(name); + } + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + computeWorldRotation(bone) { + let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation); + let x = cos * bone.a + sin * bone.b; + let y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * MathUtils.radDeg; + } + copy() { + let copy = new PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/RegionAttachment.ts + var _RegionAttachment = class extends Attachment { + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local rotation. */ + rotation = 0; + /** The width of the region attachment in Spine. */ + width = 0; + /** The height of the region attachment in Spine. */ + height = 0; + /** The color to tint the region attachment. */ + color = new Color(1, 1, 1, 1); + /** The name of the texture region for this attachment. */ + path; + region = null; + sequence = null; + /** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex. + * + * See {@link #updateOffset()}. */ + offset = Utils.newFloatArray(8); + uvs = Utils.newFloatArray(8); + tempColor = new Color(1, 1, 1, 1); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let region = this.region; + let uvs = this.uvs; + if (region == null) { + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + uvs[4] = 1; + uvs[5] = 1; + uvs[6] = 1; + uvs[7] = 0; + return; + } + let regionScaleX = this.width / this.region.originalWidth * this.scaleX; + let regionScaleY = this.height / this.region.originalHeight * this.scaleY; + let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + let localX2 = localX + this.region.width * regionScaleX; + let localY2 = localY + this.region.height * regionScaleY; + let radians = this.rotation * Math.PI / 180; + let cos = Math.cos(radians); + let sin = Math.sin(radians); + let x = this.x, y = this.y; + let localXCos = localX * cos + x; + let localXSin = localX * sin; + let localYCos = localY * cos + y; + let localYSin = localY * sin; + let localX2Cos = localX2 * cos + x; + let localX2Sin = localX2 * sin; + let localY2Cos = localY2 * cos + y; + let localY2Sin = localY2 * sin; + let offset = this.offset; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + if (region.degrees == 90) { + uvs[0] = region.u2; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + } else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + } + /** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may + * be changed. + *

+ * See World transforms in the Spine + * Runtimes Guide. + * @param worldVertices The output world vertices. Must have a length >= offset + 8. + * @param offset The worldVertices index to begin writing values. + * @param stride The number of worldVertices entries between the value pairs written. */ + computeWorldVertices(slot, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + let bone = slot.bone; + let vertexOffset = this.offset; + let x = bone.worldX, y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = 0, offsetY = 0; + offsetX = vertexOffset[0]; + offsetY = vertexOffset[1]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[2]; + offsetY = vertexOffset[3]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[4]; + offsetY = vertexOffset[5]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[6]; + offsetY = vertexOffset[7]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + } + copy() { + let copy = new _RegionAttachment(this.name, this.path); + copy.region = this.region; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + return copy; + } + }; + var RegionAttachment = _RegionAttachment; + __publicField(RegionAttachment, "X1", 0); + __publicField(RegionAttachment, "Y1", 1); + __publicField(RegionAttachment, "C1R", 2); + __publicField(RegionAttachment, "C1G", 3); + __publicField(RegionAttachment, "C1B", 4); + __publicField(RegionAttachment, "C1A", 5); + __publicField(RegionAttachment, "U1", 6); + __publicField(RegionAttachment, "V1", 7); + __publicField(RegionAttachment, "X2", 8); + __publicField(RegionAttachment, "Y2", 9); + __publicField(RegionAttachment, "C2R", 10); + __publicField(RegionAttachment, "C2G", 11); + __publicField(RegionAttachment, "C2B", 12); + __publicField(RegionAttachment, "C2A", 13); + __publicField(RegionAttachment, "U2", 14); + __publicField(RegionAttachment, "V2", 15); + __publicField(RegionAttachment, "X3", 16); + __publicField(RegionAttachment, "Y3", 17); + __publicField(RegionAttachment, "C3R", 18); + __publicField(RegionAttachment, "C3G", 19); + __publicField(RegionAttachment, "C3B", 20); + __publicField(RegionAttachment, "C3A", 21); + __publicField(RegionAttachment, "U3", 22); + __publicField(RegionAttachment, "V3", 23); + __publicField(RegionAttachment, "X4", 24); + __publicField(RegionAttachment, "Y4", 25); + __publicField(RegionAttachment, "C4R", 26); + __publicField(RegionAttachment, "C4G", 27); + __publicField(RegionAttachment, "C4B", 28); + __publicField(RegionAttachment, "C4A", 29); + __publicField(RegionAttachment, "U4", 30); + __publicField(RegionAttachment, "V4", 31); + + // spine-core/src/AtlasAttachmentLoader.ts + var AtlasAttachmentLoader = class { + atlas; + constructor(atlas) { + this.atlas = atlas; + } + loadSequence(name, basePath, sequence) { + let regions = sequence.regions; + for (let i = 0, n = regions.length; i < n; i++) { + let path = sequence.getPath(basePath, i); + let region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")"); + regions[i] = region; + } + } + newRegionAttachment(skin, name, path, sequence) { + let attachment = new RegionAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newMeshAttachment(skin, name, path, sequence) { + let attachment = new MeshAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newBoundingBoxAttachment(skin, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, name) { + return new ClippingAttachment(name); + } + }; + + // spine-core/src/BoneData.ts + var BoneData = class { + /** The index of the bone in {@link Skeleton#getBones()}. */ + index = 0; + /** The name of the bone, which is unique across all bones in the skeleton. */ + name; + /** @returns May be null. */ + parent = null; + /** The bone's length. */ + length = 0; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local shearX. */ + shearX = 0; + /** The local shearX. */ + shearY = 0; + /** The transform mode for how parent world transforms affect this bone. */ + transformMode = TransformMode.Normal; + /** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this + * bone. + * @see Skin#bones */ + skinRequired = false; + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually + * rendered at runtime. */ + color = new Color(); + constructor(index, name, parent) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + }; + var TransformMode = /* @__PURE__ */ ((TransformMode2) => { + TransformMode2[TransformMode2["Normal"] = 0] = "Normal"; + TransformMode2[TransformMode2["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode2[TransformMode2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode2[TransformMode2["NoScale"] = 3] = "NoScale"; + TransformMode2[TransformMode2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + return TransformMode2; + })(TransformMode || {}); + + // spine-core/src/Bone.ts + var Bone = class { + /** The bone's setup pose data. */ + data; + /** The skeleton this bone belongs to. */ + skeleton; + /** The parent bone, or null if this is the root bone. */ + parent = null; + /** The immediate children of this bone. */ + children = new Array(); + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 0; + /** The local scaleY. */ + scaleY = 0; + /** The local shearX. */ + shearX = 0; + /** The local shearY. */ + shearY = 0; + /** The applied local x translation. */ + ax = 0; + /** The applied local y translation. */ + ay = 0; + /** The applied local rotation in degrees, counter clockwise. */ + arotation = 0; + /** The applied local scaleX. */ + ascaleX = 0; + /** The applied local scaleY. */ + ascaleY = 0; + /** The applied local shearX. */ + ashearX = 0; + /** The applied local shearY. */ + ashearY = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + a = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + b = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + c = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + d = 0; + /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldY = 0; + /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldX = 0; + sorted = false; + active = false; + /** @param parent May be null. */ + constructor(data, skeleton, parent) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + /** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the + * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */ + isActive() { + return this.active; + } + /** Computes the world transform using the parent bone and this bone's local applied transform. */ + update() { + this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY); + } + /** Computes the world transform using the parent bone and this bone's local transform. + * + * See {@link #updateWorldTransformWith()}. */ + updateWorldTransform() { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + } + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + let parent = this.parent; + if (!parent) { + let skeleton = this.skeleton; + let rotationY = rotation + 90 + shearY; + let sx = skeleton.scaleX; + let sy = skeleton.scaleY; + this.a = MathUtils.cosDeg(rotation + shearX) * scaleX * sx; + this.b = MathUtils.cosDeg(rotationY) * scaleY * sx; + this.c = MathUtils.sinDeg(rotation + shearX) * scaleX * sy; + this.d = MathUtils.sinDeg(rotationY) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case 0 /* Normal */: { + let rotationY = rotation + 90 + shearY; + let la = MathUtils.cosDeg(rotation + shearX) * scaleX; + let lb = MathUtils.cosDeg(rotationY) * scaleY; + let lc = MathUtils.sinDeg(rotation + shearX) * scaleX; + let ld = MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case 1 /* OnlyTranslation */: { + let rotationY = rotation + 90 + shearY; + this.a = MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = MathUtils.cosDeg(rotationY) * scaleY; + this.c = MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case 2 /* NoRotationOrReflection */: { + let s = pa * pa + pc * pc; + let prx = 0; + if (s > 1e-4) { + s = Math.abs(pa * pd - pb * pc) / s; + pa /= this.skeleton.scaleX; + pc /= this.skeleton.scaleY; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * MathUtils.radDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg; + } + let rx = rotation + shearX - prx; + let ry = rotation + shearY - prx + 90; + let la = MathUtils.cosDeg(rx) * scaleX; + let lb = MathUtils.cosDeg(ry) * scaleY; + let lc = MathUtils.sinDeg(rx) * scaleX; + let ld = MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + let cos = MathUtils.cosDeg(rotation); + let sin = MathUtils.sinDeg(rotation); + let za = (pa * cos + pb * sin) / this.skeleton.scaleX; + let zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(za * za + zc * zc); + if (s > 1e-5) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.data.transformMode == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + let r = Math.PI / 2 + Math.atan2(zc, za); + let zb = Math.cos(r) * s; + let zd = Math.sin(r) * s; + let la = MathUtils.cosDeg(shearX) * scaleX; + let lb = MathUtils.cosDeg(90 + shearY) * scaleY; + let lc = MathUtils.sinDeg(shearX) * scaleX; + let ld = MathUtils.sinDeg(90 + shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + } + /** Sets this bone's local transform to the setup pose. */ + setToSetupPose() { + let data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + } + /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ + getWorldRotationX() { + return Math.atan2(this.c, this.a) * MathUtils.radDeg; + } + /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ + getWorldRotationY() { + return Math.atan2(this.d, this.b) * MathUtils.radDeg; + } + /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + /** Computes the applied transform values from the world transform. + * + * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, etc) then this method should be called so + * the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply other + * constraints). + * + * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after + * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ + updateAppliedTransform() { + let parent = this.parent; + if (!parent) { + this.ax = this.worldX - this.skeleton.x; + this.ay = this.worldY - this.skeleton.y; + this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + let pid = 1 / (pa * pd - pb * pc); + let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = dx * pd * pid - dy * pb * pid; + this.ay = dy * pa * pid - dx * pc * pid; + let ia = pid * pd; + let id = pid * pa; + let ib = pid * pb; + let ic = pid * pc; + let ra = ia * this.a - ib * this.c; + let rb = ia * this.b - ib * this.d; + let rc = id * this.c - ic * this.a; + let rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 1e-4) { + let det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg; + } else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg; + } + } + /** Transforms a point from world coordinates to the bone's local coordinates. */ + worldToLocal(world) { + let invDet = 1 / (this.a * this.d - this.b * this.c); + let x = world.x - this.worldX, y = world.y - this.worldY; + world.x = x * this.d * invDet - y * this.b * invDet; + world.y = y * this.a * invDet - x * this.c * invDet; + return world; + } + /** Transforms a point from the bone's local coordinates to world coordinates. */ + localToWorld(local) { + let x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + /** Transforms a world rotation to a local rotation. */ + worldToLocalRotation(worldRotation) { + let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX; + } + /** Transforms a local rotation to a world rotation. */ + localToWorldRotation(localRotation) { + localRotation -= this.rotation - this.shearX; + let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + /** Rotates the world transform the specified amount. + *

+ * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and {@link #update()} will + * need to be called on any child bones, recursively. */ + rotateWorld(degrees) { + let a = this.a, b = this.b, c = this.c, d = this.d; + let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + } + }; + + // spine-core/src/ConstraintData.ts + var ConstraintData = class { + constructor(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } + }; + + // spine-core/src/AssetManagerBase.ts + var AssetManagerBase = class { + pathPrefix = ""; + textureLoader; + downloader; + assets = {}; + errors = {}; + toLoad = 0; + loaded = 0; + constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) { + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader; + } + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.assets[path] = asset; + if (callback) + callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) + callback(path, message); + } + loadAll() { + let promise = new Promise((resolve, reject) => { + let check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) + reject(this.errors); + else + resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`); + }); + } + loadText(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`); + }); + } + loadTexture(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + let isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) + return response.blob(); + this.error(error, path, `Couldn't load image: ${path}`); + return null; + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) + this.success(success, path, this.textureLoader(bitmap)); + }); + } else { + let image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + this.success(success, path, this.textureLoader(image)); + }; + image.onerror = () => { + this.error(error, path, `Couldn't load image: ${path}`); + }; + if (this.downloader.rawDataUris[path]) + path = this.downloader.rawDataUris[path]; + image.src = path; + } + } + loadTextureAtlas(path, success = () => { + }, error = () => { + }, fileAlias) { + let index = path.lastIndexOf("/"); + let parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + this.downloader.downloadText(path, (atlasText) => { + try { + let atlas = new TextureAtlas(atlasText); + let toLoad = atlas.pages.length, abort = false; + for (let page of atlas.pages) { + this.loadTexture( + !fileAlias ? parent + page.name : fileAlias[page.name], + (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad == 0) + this.success(success, path, atlas); + } + }, + (imagePath, message) => { + if (!abort) + this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`); + abort = true; + } + ); + } + } catch (e) { + this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`); + } + }, (status, responseText) => { + this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`); + }); + } + get(path) { + return this.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset) + return asset; + let error = this.errors[path]; + throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + } + remove(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + delete this.assets[path]; + return asset; + } + removeAll() { + for (let key in this.assets) { + let asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + } + isLoadingComplete() { + return this.toLoad == 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } + }; + var Downloader = class { + callbacks = {}; + rawDataUris = {}; + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx != -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx == -1) + throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToString(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", url, true); + let done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToUint8Array(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + let onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status == 200 || request.status == 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) + return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + let callbacks = this.callbacks[url]; + delete this.callbacks[url]; + let args = status == 200 || status == 0 ? [data] : [status, data]; + for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) + callbacks[i].apply(null, args); + } + }; + + // spine-core/src/Event.ts + var Event = class { + data; + intValue = 0; + floatValue = 0; + stringValue = null; + time = 0; + volume = 0; + balance = 0; + constructor(time, data) { + if (!data) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + }; + + // spine-core/src/EventData.ts + var EventData = class { + name; + intValue = 0; + floatValue = 0; + stringValue = null; + audioPath = null; + volume = 0; + balance = 0; + constructor(name) { + this.name = name; + } + }; + + // spine-core/src/IkConstraint.ts + var IkConstraint = class { + /** The IK constraint's setup pose data. */ + data; + /** The bones that will be modified by this IK constraint. */ + bones; + /** The bone that is the IK target. */ + target; + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 1; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find bone ${data.target.name}`); + this.target = target; + } + isActive() { + return this.active; + } + update() { + if (this.mix == 0) + return; + let target = this.target; + let bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix); + break; + } + } + /** Applies 1 bone IK. The target is specified in the world coordinate system. */ + apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) { + let p = bone.parent; + if (!p) + throw new Error("IK bone must have parent."); + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.data.transformMode) { + case 1 /* OnlyTranslation */: + tx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX); + ty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY); + break; + case 2 /* NoRotationOrReflection */: + let s = Math.abs(pa * pd - pb * pc) / Math.max(1e-4, pa * pa + pc * pc); + let sa = pa / bone.skeleton.scaleX; + let sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg; + default: + let x = targetX - p.worldX, y = targetY - p.worldY; + let d = pa * pd - pb * pc; + if (Math.abs(d) <= 1e-4) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + } + rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + let sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.data.transformMode) { + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); + if (compress && dd < b || stretch && dd > b && b > 1e-4) { + let s = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + bone.updateWorldTransformWith( + bone.ax, + bone.ay, + bone.arotation + rotationIK * alpha, + sx, + sy, + bone.ashearX, + bone.ashearY + ); + } + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ + apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) { + let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + let u = Math.abs(psx - psy) <= 1e-4; + if (!u || stretch) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + let pp = parent.parent; + if (!pp) + throw new Error("IK parent must itself have a parent."); + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; + id = Math.abs(id) <= 1e-4 ? 0 : 1 / id; + let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 1e-4) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5; + let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) + sy *= a; + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + let c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + if (r * r <= dd) { + y = Math.sqrt(dd - r * r) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + let os = Math.atan2(cy, cx) * s2; + let rotation = parent.arotation; + a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + } + }; + + // spine-core/src/IkConstraintData.ts + var IkConstraintData = class extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ + bones = new Array(); + /** The bone that is the IK target. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 1; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone + * is scaled on both the X and Y axes. */ + uniform = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 1; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/PathConstraintData.ts + var PathConstraintData = class extends ConstraintData { + /** The bones that will be modified by this path constraint. */ + bones = new Array(); + /** The slot whose path attachment will be used to constrained the bones. */ + _target = null; + set target(slotData) { + this._target = slotData; + } + get target() { + if (!this._target) + throw new Error("SlotData not set."); + else + return this._target; + } + /** The mode for positioning the first bone on the path. */ + positionMode = PositionMode.Fixed; + /** The mode for positioning the bones after the first bone on the path. */ + spacingMode = SpacingMode.Fixed; + /** The mode for adjusting the rotation of the bones. */ + rotateMode = RotateMode.Chain; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + constructor(name) { + super(name, 0, false); + } + }; + var PositionMode = /* @__PURE__ */ ((PositionMode2) => { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + return PositionMode2; + })(PositionMode || {}); + var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + return SpacingMode2; + })(SpacingMode || {}); + var RotateMode = /* @__PURE__ */ ((RotateMode2) => { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + return RotateMode2; + })(RotateMode || {}); + + // spine-core/src/PathConstraint.ts + var _PathConstraint = class { + /** The path constraint's setup pose data. */ + data; + /** The bones that will be modified by this path constraint. */ + bones; + /** The slot whose path attachment will be used to constrained the bones. */ + target; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + spaces = new Array(); + positions = new Array(); + world = new Array(); + curves = new Array(); + lengths = new Array(); + segments = new Array(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0, n = data.bones.length; i < n; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findSlot(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}`); + this.target = target; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + isActive() { + return this.active; + } + update() { + let attachment = this.target.getAttachment(); + if (!(attachment instanceof PathAttachment)) + return; + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) + return; + let data = this.data; + let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */; + let bones = this.bones; + let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + let spacing = this.spacing; + switch (data.spacingMode) { + case 2 /* Percent */: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) + lengths[i] = 0; + else { + let x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case 3 /* Proportional */: + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + let lengthSpacing = data.spacingMode == 0 /* Length */; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + let positions = this.computeWorldPositions(attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation == 0) + tip = data.rotateMode == 1 /* Chain */; + else { + tip = false; + let p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, p = 3; i < boneCount; i++, p += 3) { + let bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + let length = lengths[i]; + if (length != 0) { + let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + let length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.updateAppliedTransform(); + } + } + computeWorldPositions(path, spacesCount, tangents) { + let target = this.target; + let position = this.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world; + let closed2 = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + let lengths = path.lengths; + curveCount -= closed2 ? 1 : 2; + let pathLength2 = lengths[curveCount]; + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier2 = pathLength2; + break; + case 3 /* Proportional */: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed2) { + p %= pathLength2; + if (p < 0) + p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve != _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve != _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + let length = lengths[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed2 && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition( + p, + world[0], + world[1], + world[2], + world[3], + world[4], + world[5], + world[6], + world[7], + out, + o, + tangents || i > 0 && space == 0 + ); + } + return out; + } + if (closed2) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + let curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier = pathLength; + break; + case 3 /* Proportional */: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + let segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed2) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + let length = curves[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + let length = segments[segment]; + if (p > length) + continue; + if (segment == 0) + p /= length; + else { + let prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } + }; + var PathConstraint = _PathConstraint; + __publicField(PathConstraint, "NONE", -1); + __publicField(PathConstraint, "BEFORE", -2); + __publicField(PathConstraint, "AFTER", -3); + __publicField(PathConstraint, "epsilon", 1e-5); + + // spine-core/src/Slot.ts + var Slot = class { + /** The slot's setup pose data. */ + data; + /** The bone this slot belongs to. */ + bone; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color; + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + attachment = null; + attachmentState = 0; + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence#getSetupIndex()}. */ + sequenceIndex = -1; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * + * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */ + deform = new Array(); + constructor(data, bone) { + if (!data) + throw new Error("data cannot be null."); + if (!bone) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new Color(); + this.darkColor = !data.darkColor ? null : new Color(); + this.setToSetupPose(); + } + /** The skeleton this slot belongs to. */ + getSkeleton() { + return this.bone.skeleton; + } + /** The current attachment for the slot, or null if the slot has no attachment. */ + getAttachment() { + return this.attachment; + } + /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the + * specified attachment. */ + setAttachment(attachment) { + if (this.attachment == attachment) + return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + /** Sets this slot to the setup pose. */ + setToSetupPose() { + this.color.setFromColor(this.data.color); + if (this.darkColor) + this.darkColor.setFromColor(this.data.darkColor); + if (!this.data.attachmentName) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } + }; + + // spine-core/src/TransformConstraint.ts + var TransformConstraint = class { + /** The transform constraint's setup pose data. */ + data; + /** The bones that will be modified by this transform constraint. */ + bones; + /** The target bone whose world transform will be copied to the constrained bones. */ + target; + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + temp = new Vector2(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}.`); + this.target = target; + } + isActive() { + return this.active; + } + update() { + if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) + return; + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + } + applyAbsoluteWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect; + let offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * mixX; + bone.worldY += (temp.y - bone.worldY) * mixY; + } + if (mixScaleX != 0) { + let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + if (s != 0) + s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + if (s != 0) + s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let b = bone.b, d = bone.d; + let by = Math.atan2(d, b); + let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r = by + (r + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyRelativeWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * mixX; + bone.worldY += temp.y * mixY; + } + if (mixScaleX != 0) { + let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + let b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyAbsoluteLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation; + if (mixRotate != 0) { + let r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360; + rotation += r * mixRotate; + } + let x = bone.ax, y = bone.ay; + x += (target.ax - x + this.data.offsetX) * mixX; + y += (target.ay - y + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY; + let shearY = bone.ashearY; + if (mixShearY != 0) { + let r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360; + shearY += r * mixShearY; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + applyRelativeLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax + (target.ax + this.data.offsetX) * mixX; + let y = bone.ay + (target.ay + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1); + let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1); + let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + }; + + // spine-core/src/Skeleton.ts + var _Skeleton = class { + /** The skeleton's setup pose data. */ + data; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones; + /** The skeleton's slots. */ + slots; + /** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */ + drawOrder; + /** The skeleton's IK constraints. */ + ikConstraints; + /** The skeleton's transform constraints. */ + transformConstraints; + /** The skeleton's path constraints. */ + pathConstraints; + /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */ + _updateCache = new Array(); + /** The skeleton's current skin. May be null. */ + skin = null; + /** The color to tint all the skeleton's attachments. */ + color; + /** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + scaleX = 1; + /** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + _scaleY = 1; + get scaleY() { + return _Skeleton.yDown ? -this._scaleY : this._scaleY; + } + set scaleY(scaleY) { + this._scaleY = scaleY; + } + /** Sets the skeleton X position, which is added to the root bone worldX position. */ + x = 0; + /** Sets the skeleton Y position, which is added to the root bone worldY position. */ + y = 0; + constructor(data) { + if (!data) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, this, null); + else { + let parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (let i = 0; i < data.slots.length; i++) { + let slotData = data.slots[i]; + let bone = this.bones[slotData.boneData.index]; + let slot = new Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (let i = 0; i < data.ikConstraints.length; i++) { + let ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (let i = 0; i < data.transformConstraints.length; i++) { + let transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (let i = 0; i < data.pathConstraints.length; i++) { + let pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new PathConstraint(pathConstraintData, this)); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones, + * constraints, or weighted path attachments are added or removed. */ + updateCache() { + let updateCache = this._updateCache; + updateCache.length = 0; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin) { + let skinBones = this.skin.bones; + for (let i = 0, n = this.skin.bones.length; i < n; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + let ikConstraints = this.ikConstraints; + let transformConstraints = this.transformConstraints; + let pathConstraints = this.pathConstraints; + let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length; + let constraintCount = ikCount + transformCount + pathCount; + outer: + for (let i = 0; i < constraintCount; i++) { + for (let ii = 0; ii < ikCount; ii++) { + let constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < transformCount; ii++) { + let constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < pathCount; ii++) { + let constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + } + for (let i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + } + sortIkConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let target = constraint.target; + this.sortBone(target); + let constrained = constraint.bones; + let parent = constrained[0]; + this.sortBone(parent); + if (constrained.length == 1) { + this._updateCache.push(constraint); + this.sortReset(parent.children); + } else { + let child = constrained[constrained.length - 1]; + this.sortBone(child); + this._updateCache.push(constraint); + this.sortReset(parent.children); + child.sorted = true; + } + } + sortPathConstraint(constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let slot = constraint.target; + let slotIndex = slot.data.index; + let slotBone = slot.bone; + if (this.skin) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (let i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + let attachment = slot.getAttachment(); + if (attachment instanceof PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + let constrained = constraint.bones; + let boneCount = constrained.length; + for (let i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortTransformConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(constraint.target); + let constrained = constraint.bones; + let boneCount = constrained.length; + if (constraint.data.local) { + for (let i = 0; i < boneCount; i++) { + let child = constrained[i]; + this.sortBone(child.parent); + this.sortBone(child); + } + } else { + for (let i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortPathConstraintAttachment(skin, slotIndex, slotBone) { + let attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (let key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + } + sortPathConstraintAttachmentWith(attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) + return; + let pathBones = attachment.bones; + if (!pathBones) + this.sortBone(slotBone); + else { + let bones = this.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + this.sortBone(bones[pathBones[i++]]); + } + } + } + sortBone(bone) { + if (!bone) + return; + if (bone.sorted) + return; + let parent = bone.parent; + if (parent) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (!bone.active) + continue; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + } + /** Updates the world transform for each bone and applies all constraints. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransform() { + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(); + } + updateWorldTransformWith(parent) { + let rootBone = this.getRootBone(); + if (!rootBone) + throw new Error("Root bone must not be null."); + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + rootBone.worldX = pa * this.x + pb * this.y + parent.worldX; + rootBone.worldY = pc * this.x + pd * this.y + parent.worldY; + let rotationY = rootBone.rotation + 90 + rootBone.shearY; + let la = MathUtils.cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX; + let lb = MathUtils.cosDeg(rotationY) * rootBone.scaleY; + let lc = MathUtils.sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX; + let ld = MathUtils.sinDeg(rotationY) * rootBone.scaleY; + rootBone.a = (pa * la + pb * lc) * this.scaleX; + rootBone.b = (pa * lb + pb * ld) * this.scaleX; + rootBone.c = (pc * la + pd * lc) * this.scaleY; + rootBone.d = (pc * lb + pd * ld) * this.scaleY; + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) { + let updatable = updateCache[i]; + if (updatable != rootBone) + updatable.update(); + } + } + /** Sets the bones, constraints, and slots to their setup pose values. */ + setToSetupPose() { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + } + /** Sets the bones and constraints to their setup pose values. */ + setBonesToSetupPose() { + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let constraint = ikConstraints[i]; + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + let data = constraint.data; + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + } + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + let data = constraint.data; + constraint.position = data.position; + constraint.spacing = data.spacing; + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + } + } + /** Sets the slots and draw order to their setup pose values. */ + setSlotsToSetupPose() { + let slots = this.slots; + Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + } + /** @returns May return null. */ + getRootBone() { + if (this.bones.length == 0) + return null; + return this.bones[0]; + } + /** @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + } + /** Sets a skin by name. + * + * See {@link #setSkin()}. */ + setSkinByName(skinName) { + let skin = this.data.findSkin(skinName); + if (!skin) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + } + /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the + * skin is changed, {@link #updateCache()} is called. + * + * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no + * old skin, each slot's setup mode attachment is attached from the new skin. + * + * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the + * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + * @param newSkin May be null. */ + setSkin(newSkin) { + if (newSkin == this.skin) + return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let name = slot.data.attachmentName; + if (name) { + let attachment = newSkin.getAttachment(i, name); + if (attachment) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment + * name. + * + * See {@link #getAttachment()}. + * @returns May be null. */ + getAttachmentByName(slotName, attachmentName) { + let slot = this.data.findSlot(slotName); + if (!slot) + throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.index, attachmentName); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. + * @returns May be null. */ + getAttachment(slotIndex, attachmentName) { + if (!attachmentName) + throw new Error("attachmentName cannot be null."); + if (this.skin) { + let attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) + return attachment; + } + if (this.data.defaultSkin) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + } + /** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with + * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}. + * @param attachmentName May be null to clear the slot's attachment. */ + setAttachment(slotName, attachmentName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) { + let attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (!attachment) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let ikConstraint = ikConstraints[i]; + if (ikConstraint.data.name == constraintName) + return ikConstraint; + } + return null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it repeatedly. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + if (constraint.data.name == constraintName) + return constraint; + } + return null; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`. + * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */ + getBoundsRect() { + let offset = new Vector2(); + let size = new Vector2(); + this.getBounds(offset, size); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. */ + getBounds(offset, size, temp = new Array(2)) { + if (!offset) + throw new Error("offset cannot be null."); + if (!size) + throw new Error("size cannot be null."); + let drawOrder = this.drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + if (!slot.bone.active) + continue; + let verticesLength = 0; + let vertices = null; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot, vertices, 0, 2); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices) { + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + }; + var Skeleton = _Skeleton; + __publicField(Skeleton, "yDown", false); + + // spine-core/src/SkeletonData.ts + var SkeletonData = class { + /** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */ + name = null; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones = new Array(); + // Ordered parents first. + /** The skeleton's slots. */ + slots = new Array(); + // Setup pose draw order. + skins = new Array(); + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See {@link Skeleton#getAttachmentByName()}. + * May be null. */ + defaultSkin = null; + /** The skeleton's events. */ + events = new Array(); + /** The skeleton's animations. */ + animations = new Array(); + /** The skeleton's IK constraints. */ + ikConstraints = new Array(); + /** The skeleton's transform constraints. */ + transformConstraints = new Array(); + /** The skeleton's path constraints. */ + pathConstraints = new Array(); + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + x = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + y = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ + width = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ + height = 0; + /** The Spine version used to export the skeleton data, or null. */ + version = null; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */ + hash = null; + // Nonessential + /** The dopesheet FPS in Spine. Available only when nonessential data was exported. */ + fps = 0; + /** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + imagesPath = null; + /** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + audioPath = null; + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + } + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSkin(skinName) { + if (!skinName) + throw new Error("skinName cannot be null."); + let skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) { + let skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + } + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findEvent(eventDataName) { + if (!eventDataName) + throw new Error("eventDataName cannot be null."); + let events = this.events; + for (let i = 0, n = events.length; i < n; i++) { + let event = events[i]; + if (event.name == eventDataName) + return event; + } + return null; + } + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @returns May be null. */ + findAnimation(animationName) { + if (!animationName) + throw new Error("animationName cannot be null."); + let animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) { + let animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + let constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it multiple times. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + let constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + let pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + let constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + }; + + // spine-core/src/Skin.ts + var SkinEntry = class { + constructor(slotIndex = 0, name, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + }; + var Skin = class { + /** The skin's name, which is unique across all skins in the skeleton. */ + name; + attachments = new Array(); + bones = Array(); + constraints = new Array(); + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + /** Adds an attachment to the skin for the specified slot index and name. */ + setAttachment(slotIndex, name, attachment) { + if (!attachment) + throw new Error("attachment cannot be null."); + let attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (!attachment.attachment) + continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + } + /** Returns the attachment for the specified slot index and name, or null. */ + getAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + } + /** Removes the attachment in the skin for the specified slot index and name, if any. */ + removeAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + if (dictionary) + delete dictionary[name]; + } + /** Returns all attachments in this skin. */ + getAttachments() { + let entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + let slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + /** Returns all attachments in this skin for the specified slot index. */ + getAttachmentsForSlot(slotIndex, attachments) { + let slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + /** Clears all attachments, bones, and constraints. */ + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + let slot = skeleton.slots[i]; + let slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + let dictionary = oldSkin.attachments[slotIndex]; + for (let key in dictionary) { + let skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + let attachment = this.getAttachment(slotIndex, key); + if (attachment) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } + }; + + // spine-core/src/SlotData.ts + var SlotData = class { + /** The index of the slot in {@link Skeleton#getSlots()}. */ + index = 0; + /** The name of the slot, which is unique across all slots in the skeleton. */ + name; + /** The bone this slot belongs to. */ + boneData; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ + attachmentName = null; + /** The blend mode for drawing the slot's attachment. */ + blendMode = BlendMode.Normal; + constructor(index, name, boneData) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + if (!boneData) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + }; + var BlendMode = /* @__PURE__ */ ((BlendMode3) => { + BlendMode3[BlendMode3["Normal"] = 0] = "Normal"; + BlendMode3[BlendMode3["Additive"] = 1] = "Additive"; + BlendMode3[BlendMode3["Multiply"] = 2] = "Multiply"; + BlendMode3[BlendMode3["Screen"] = 3] = "Screen"; + return BlendMode3; + })(BlendMode || {}); + + // spine-core/src/TransformConstraintData.ts + var TransformConstraintData = class extends ConstraintData { + /** The bones that will be modified by this transform constraint. */ + bones = new Array(); + /** The target bone whose world transform will be copied to the constrained bones. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** An offset added to the constrained bone X translation. */ + offsetX = 0; + /** An offset added to the constrained bone Y translation. */ + offsetY = 0; + /** An offset added to the constrained bone scaleX. */ + offsetScaleX = 0; + /** An offset added to the constrained bone scaleY. */ + offsetScaleY = 0; + /** An offset added to the constrained bone shearY. */ + offsetShearY = 0; + relative = false; + local = false; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + attachmentLoader; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + skeletonData.name = ""; + let input = new BinaryInput(binary); + let lowHash = input.readInt32(); + let highHash = input.readInt32(); + skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + let nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let str = input.readString(); + if (!str) + throw new Error("String in string table must not be null."); + input.strings.push(str); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Bone name must not be null."); + let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + let data = new BoneData(i, name, parent); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.transformMode = input.readInt(true); + data.skinRequired = input.readBoolean(); + if (nonessential) + Color.rgba8888ToColor(data.color, input.readInt32()); + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let slotName = input.readString(); + if (!slotName) + throw new Error("Slot name must not be null."); + let boneData = skeletonData.bones[input.readInt(true)]; + let data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.color, input.readInt32()); + let darkColor = input.readInt32(); + if (darkColor != -1) + Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("IK constraint data name must not be null."); + let data = new IkConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.mix = input.readFloat(); + data.softness = input.readFloat() * scale; + data.bendDirection = input.readByte(); + data.compress = input.readBoolean(); + data.stretch = input.readBoolean(); + data.uniform = input.readBoolean(); + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Transform constraint data name must not be null."); + let data = new TransformConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + data.local = input.readBoolean(); + data.relative = input.readBoolean(); + data.offsetRotation = input.readFloat(); + data.offsetX = input.readFloat() * scale; + data.offsetY = input.readFloat() * scale; + data.offsetScaleX = input.readFloat(); + data.offsetScaleY = input.readFloat(); + data.offsetShearY = input.readFloat(); + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + data.mixScaleX = input.readFloat(); + data.mixScaleY = input.readFloat(); + data.mixShearY = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Path constraint data name must not be null."); + let data = new PathConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + data.positionMode = input.readInt(true); + data.spacingMode = input.readInt(true); + data.rotateMode = input.readInt(true); + data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) { + let skin = this.readSkin(input, skeletonData, false, nonessential); + if (!skin) + throw new Error("readSkin() should not have returned null."); + skeletonData.skins[i] = skin; + } + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) + throw new Error("Not skin found for linked mesh."); + if (!linkedMesh.parent) + throw new Error("Linked mesh parent must not be null"); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let eventName = input.readStringRef(); + if (!eventName) + throw new Error(); + let data = new EventData(eventName); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let animationName = input.readString(); + if (!animationName) + throw new Error("Animatio name must not be null."); + skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData)); + } + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) + return null; + skin = new Skin("default"); + } else { + let skinName = input.readStringRef(); + if (!skinName) + throw new Error("Skin name must not be null."); + skin = new Skin(skinName); + skin.bones.length = input.readInt(true); + for (let i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let name = input.readStringRef(); + if (!name) + throw new Error("Attachment name must not be null"); + let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + if (attachment) + skin.setAttachment(slotIndex, name, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + let scale = this.scale; + let name = input.readStringRef(); + if (!name) + name = attachmentName; + switch (input.readByte()) { + case AttachmentType.Region: { + let path = input.readStringRef(); + let rotation = input.readFloat(); + let x = input.readFloat(); + let y = input.readFloat(); + let scaleX = input.readFloat(); + let scaleY = input.readFloat(); + let width = input.readFloat(); + let height = input.readFloat(); + let color = input.readInt32(); + let sequence = this.readSequence(input); + if (!path) + path = name; + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.sequence = sequence; + if (sequence == null) + region.updateRegion(); + return region; + } + case AttachmentType.BoundingBox: { + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let color = nonessential ? input.readInt32() : 0; + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + box.worldVerticesLength = vertexCount << 1; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(box.color, color); + return box; + } + case AttachmentType.Mesh: { + let path = input.readStringRef(); + let color = input.readInt32(); + let vertexCount = input.readInt(true); + let uvs = this.readFloatArray(input, vertexCount << 1, 1); + let triangles = this.readShortArray(input); + let vertices = this.readVertices(input, vertexCount); + let hullLength = input.readInt(true); + let sequence = this.readSequence(input); + let edges = []; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertexCount << 1; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + if (sequence == null) + mesh.updateRegion(); + mesh.hullLength = hullLength << 1; + mesh.sequence = sequence; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case AttachmentType.LinkedMesh: { + let path = input.readStringRef(); + let color = input.readInt32(); + let skinName = input.readStringRef(); + let parent = input.readStringRef(); + let inheritTimelines = input.readBoolean(); + let sequence = this.readSequence(input); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.sequence = sequence; + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinName, slotIndex, parent, inheritTimelines)); + return mesh; + } + case AttachmentType.Path: { + let closed2 = input.readBoolean(); + let constantSpeed = input.readBoolean(); + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + let color = nonessential ? input.readInt32() : 0; + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = closed2; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertexCount << 1; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) + Color.rgba8888ToColor(path.color, color); + return path; + } + case AttachmentType.Point: { + let rotation = input.readFloat(); + let x = input.readFloat(); + let y = input.readFloat(); + let color = nonessential ? input.readInt32() : 0; + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) + Color.rgba8888ToColor(point.color, color); + return point; + } + case AttachmentType.Clipping: { + let endSlotIndex = input.readInt(true); + let vertexCount = input.readInt(true); + let vertices = this.readVertices(input, vertexCount); + let color = nonessential ? input.readInt32() : 0; + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertexCount << 1; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + } + readSequence(input) { + if (!input.readBoolean()) + return null; + let sequence = new Sequence(input.readInt(true)); + sequence.start = input.readInt(true); + sequence.digits = input.readInt(true); + sequence.setupIndex = input.readInt(true); + return sequence; + } + readVertices(input, vertexCount) { + let scale = this.scale; + let verticesLength = vertexCount << 1; + let vertices = new Vertices(); + if (!input.readBoolean()) { + vertices.vertices = this.readFloatArray(input, verticesLength, scale); + return vertices; + } + let weights = new Array(); + let bonesArray = new Array(); + for (let i = 0; i < vertexCount; i++) { + let boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (let ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + } + readFloatArray(input, n, scale) { + let array = new Array(n); + if (scale == 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input) { + let n = input.readInt(true); + let array = new Array(n); + for (let i = 0; i < n; i++) + array[i] = input.readShort(); + return array; + } + readAnimation(input, name, skeletonData) { + input.readInt(true); + let timelines = new Array(); + let scale = this.scale; + let tempColor1 = new Color(); + let tempColor2 = new Color(); + for (let i = 0, n = input.readInt(true); i < n; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + let timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + let bezierCount = input.readInt(true); + let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + let bezierCount = input.readInt(true); + let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + let bezierCount = input.readInt(true); + let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let na = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + let bezierCount = input.readInt(true); + let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_TRANSLATE: + timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEX: + timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEY: + timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_SCALE: + timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEX: + timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEY: + timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEAR: + timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARX: + timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARY: + timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mix = input.readFloat(), softness = input.readFloat() * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, input.readByte(), input.readBoolean(), input.readBoolean()); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mix2 = input.readFloat(), softness2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true); + let data = skeletonData.pathConstraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + switch (input.readByte()) { + case PATH_POSITION: + timelines.push(readTimeline1( + input, + new PathConstraintPositionTimeline(input.readInt(true), input.readInt(true), index), + data.positionMode == 0 /* Fixed */ ? scale : 1 + )); + break; + case PATH_SPACING: + timelines.push(readTimeline1( + input, + new PathConstraintSpacingTimeline(input.readInt(true), input.readInt(true), index), + data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1 + )); + break; + case PATH_MIX: + let timeline = new PathConstraintMixTimeline(input.readInt(true), input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + let attachmentName = input.readStringRef(); + if (!attachmentName) + throw new Error("attachmentName must not be null."); + let attachment = skin.getAttachment(slotIndex, attachmentName); + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + let vertexAttachment = attachment; + let weighted = vertexAttachment.bones; + let vertices = vertexAttachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let bezierCount = input.readInt(true); + let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end == 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = input.readInt(true); + end += start; + if (scale == 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + let timeline = new SequenceTimeline(frameCount, slotIndex, attachment); + for (let frame = 0; frame < frameCount; frame++) { + let time = input.readFloat(); + let modeAndIndex = input.readInt32(); + timeline.setFrame( + frame, + time, + SequenceModeValues[modeAndIndex & 15], + modeAndIndex >> 4, + input.readFloat() + ); + } + timelines.push(timeline); + break; + } + } + } + } + } + let drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + let timeline = new DrawOrderTimeline(drawOrderCount); + let slotCount = skeletonData.slots.length; + for (let i = 0; i < drawOrderCount; i++) { + let time = input.readFloat(); + let offsetCount = input.readInt(true); + let drawOrder = Utils.newArray(slotCount, 0); + for (let ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + let unchanged = Utils.newArray(slotCount - offsetCount, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsetCount; ii++) { + let slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + } + let eventCount = input.readInt(true); + if (eventCount > 0) { + let timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + let time = input.readFloat(); + let eventData = skeletonData.events[input.readInt(true)]; + let event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + return new Animation(name, timelines, duration); + } + }; + var BinaryInput = class { + constructor(data, strings = new Array(), index = 0, buffer = new DataView(data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + let value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + let value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + let index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + let charCount = 0; + for (let i = 0; i < byteCount; ) { + let b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + let value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() != 0; + } + }; + var LinkedMesh = class { + parent; + skin; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + var Vertices = class { + constructor(bones = null, vertices = null) { + this.bones = bones; + this.vertices = vertices; + } + }; + var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => { + AttachmentType2[AttachmentType2["Region"] = 0] = "Region"; + AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh"; + AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType2[AttachmentType2["Path"] = 4] = "Path"; + AttachmentType2[AttachmentType2["Point"] = 5] = "Point"; + AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping"; + return AttachmentType2; + })(AttachmentType || {}); + function readTimeline1(input, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) + break; + let time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; + } + function readTimeline2(input, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) + break; + let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; + } + function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); + } + var BONE_ROTATE = 0; + var BONE_TRANSLATE = 1; + var BONE_TRANSLATEX = 2; + var BONE_TRANSLATEY = 3; + var BONE_SCALE = 4; + var BONE_SCALEX = 5; + var BONE_SCALEY = 6; + var BONE_SHEAR = 7; + var BONE_SHEARX = 8; + var BONE_SHEARY = 9; + var SLOT_ATTACHMENT = 0; + var SLOT_RGBA = 1; + var SLOT_RGB = 2; + var SLOT_RGBA2 = 3; + var SLOT_RGB2 = 4; + var SLOT_ALPHA = 5; + var ATTACHMENT_DEFORM = 0; + var ATTACHMENT_SEQUENCE = 1; + var PATH_POSITION = 0; + var PATH_SPACING = 1; + var PATH_MIX = 2; + var CURVE_STEPPED = 1; + var CURVE_BEZIER = 2; + + // spine-core/src/SkeletonBounds.ts + var SkeletonBounds = class { + /** The left edge of the axis aligned bounding box. */ + minX = 0; + /** The bottom edge of the axis aligned bounding box. */ + minY = 0; + /** The right edge of the axis aligned bounding box. */ + maxX = 0; + /** The top edge of the axis aligned bounding box. */ + maxY = 0; + /** The visible bounding boxes. */ + boundingBoxes = new Array(); + /** The world vertices for the bounding box polygons. */ + polygons = new Array(); + polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + /** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding + * box's polygon. + * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the + * SkeletonBounds AABB methods will always return true. */ + update(skeleton, updateAabb) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + let boundingBoxes = this.boundingBoxes; + let polygons = this.polygons; + let polygonPool = this.polygonPool; + let slots = skeleton.slots; + let slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (attachment instanceof BoundingBoxAttachment) { + let boundingBox = attachment; + boundingBoxes.push(boundingBox); + let polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + let vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + let x = vertices[ii]; + let y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + /** Returns true if the axis aligned bounding box contains the point. */ + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + /** Returns true if the axis aligned bounding box intersects the line segment. */ + aabbIntersectsSegment(x1, y1, x2, y2) { + let minX = this.minX; + let minY = this.minY; + let maxX = this.maxX; + let maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + let m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + } + /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ + containsPoint(x, y) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains the point. */ + containsPointPolygon(polygon, x, y) { + let vertices = polygon; + let nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + let vertexY = vertices[ii + 1]; + let prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + let vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + } + /** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns + * true. */ + intersectsSegment(x1, y1, x2, y2) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains any part of the line segment. */ + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + let vertices = polygon; + let nn = polygon.length; + let width12 = x1 - x2, height12 = y1 - y2; + let det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + let x4 = vertices[ii], y4 = vertices[ii + 1]; + let det2 = x3 * y4 - y3 * x4; + let width34 = x3 - x4, height34 = y3 - y4; + let det3 = width12 * height34 - height12 * width34; + let x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + let y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + /** Returns the polygon for the specified bounding box, or null. */ + getPolygon(boundingBox) { + if (!boundingBox) + throw new Error("boundingBox cannot be null."); + let index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + } + /** The width of the axis aligned bounding box. */ + getWidth() { + return this.maxX - this.minX; + } + /** The height of the axis aligned bounding box. */ + getHeight() { + return this.maxY - this.minY; + } + }; + + // spine-core/src/Triangulator.ts + var Triangulator = class { + convexPolygons = new Array(); + convexPolygonsIndices = new Array(); + indicesArray = new Array(); + isConcaveArray = new Array(); + triangles = new Array(); + polygonPool = new Pool(() => { + return new Array(); + }); + polygonIndicesPool = new Pool(() => { + return new Array(); + }); + triangulate(verticesArray) { + let vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + let indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + let isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + let triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + let p1x = vertices[p1], p1y = vertices[p1 + 1]; + let p2x = vertices[p2], p2y = vertices[p2 + 1]; + let p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + let v = indices[ii] << 1; + let vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + let previousIndex = (vertexCount + i - 1) % vertexCount; + let nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + } + decompose(verticesArray, triangles) { + let vertices = verticesArray; + let convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + let convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + let x1 = vertices[t1], y1 = vertices[t1 + 1]; + let x2 = vertices[t2], y2 = vertices[t2 + 1]; + let x3 = vertices[t3], y3 = vertices[t3 + 1]; + let merged = false; + if (fanBaseIndex == t1) { + let o = polygon.length - 4; + let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + let firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + let o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + let firstX = polygon[0], firstY = polygon[1]; + let secondX = polygon[2], secondY = polygon[3]; + let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii == i) + continue; + let otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + let otherFirstIndex = otherIndices[0]; + let otherSecondIndex = otherIndices[1]; + let otherLastIndex = otherIndices[2]; + let otherPoly = convexPolygons[ii]; + let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + let current = indices[index] << 1; + let next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea( + vertices[previous], + vertices[previous + 1], + vertices[current], + vertices[current + 1], + vertices[next], + vertices[next + 1] + ); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + let px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + } + }; + + // spine-core/src/SkeletonClipping.ts + var SkeletonClipping = class { + triangulator = new Triangulator(); + clippingPolygon = new Array(); + clipOutput = new Array(); + clippedVertices = new Array(); + clippedTriangles = new Array(); + scratch = new Array(); + clipAttachment = null; + clippingPolygons = null; + clipStart(slot, clip) { + if (this.clipAttachment) + return 0; + this.clipAttachment = clip; + let n = clip.worldVerticesLength; + let vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + let clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) { + let polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + } + clipEndWithSlot(slot) { + if (this.clipAttachment && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + } + clipEnd() { + if (!this.clipAttachment) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let vertexSize = twoColor ? 12 : 8; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (let ii = 0; ii < clipOutputLength; ii += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + s += 3; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + continue outer; + } + } + } + } + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + clip(x1, y1, x2, y2, x3, y3, clippingArea, output) { + let originalOutput = output; + let clipped = false; + let input; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + let clippingVertices = clippingArea; + let clippingVerticesLast = clippingArea.length - 4; + for (let i = 0; ; i += 2) { + let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + let edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + let deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + let inputVertices = input; + let inputVerticesLength = input.length - 2, outputStart = output.length; + for (let ii = 0; ii < inputVerticesLength; ii += 2) { + let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + let inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + let side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + let c0 = inputY2 - inputY, c2 = inputX2 - inputX; + let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 1e-6) { + let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } else { + output.push(edgeX); + output.push(edgeY); + } + } else if (side2) { + let c0 = inputY2 - inputY, c2 = inputX2 - inputX; + let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY); + if (Math.abs(s) > 1e-6) { + let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s; + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } else { + output.push(edgeX); + output.push(edgeY); + } + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + let temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + static makeClockwise(polygon) { + let vertices = polygon; + let verticeslength = polygon.length; + let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (let i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + let x = vertices[i], y = vertices[i + 1]; + let other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + } + }; + + // spine-core/src/SkeletonJson.ts + var SkeletonJson = class { + attachmentLoader; + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(json) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + let root = typeof json === "string" ? JSON.parse(json) : json; + let skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + let boneMap = root.bones[i]; + let parent = null; + let parentName = getValue(boneMap, "parent", null); + if (parentName) + parent = skeletonData.findBone(parentName); + let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + data.x = getValue(boneMap, "x", 0) * scale; + data.y = getValue(boneMap, "y", 0) * scale; + data.rotation = getValue(boneMap, "rotation", 0); + data.scaleX = getValue(boneMap, "scaleX", 1); + data.scaleY = getValue(boneMap, "scaleY", 1); + data.shearX = getValue(boneMap, "shearX", 0); + data.shearY = getValue(boneMap, "shearY", 0); + data.transformMode = Utils.enumValue(TransformMode, getValue(boneMap, "transform", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + let color = getValue(boneMap, "color", null); + if (color) + data.color.setFromString(color); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + let slotMap = root.slots[i]; + let boneData = skeletonData.findBone(slotMap.bone); + if (!boneData) + throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotMap.name}`); + let data = new SlotData(skeletonData.slots.length, slotMap.name, boneData); + let color = getValue(slotMap, "color", null); + if (color) + data.color.setFromString(color); + let dark = getValue(slotMap, "dark", null); + if (dark) + data.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (let i = 0; i < root.ik.length; i++) { + let constraintMap = root.ik[i]; + let data = new IkConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let bone = skeletonData.findBone(constraintMap.bones[ii]); + if (!bone) + throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let target = skeletonData.findBone(constraintMap.target); + ; + if (!target) + throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`); + data.target = target; + data.mix = getValue(constraintMap, "mix", 1); + data.softness = getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = getValue(constraintMap, "compress", false); + data.stretch = getValue(constraintMap, "stretch", false); + data.uniform = getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (let i = 0; i < root.transform.length; i++) { + let constraintMap = root.transform[i]; + let data = new TransformConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findBone(targetName); + if (!target) + throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`); + data.target = target; + data.local = getValue(constraintMap, "local", false); + data.relative = getValue(constraintMap, "relative", false); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.offsetX = getValue(constraintMap, "x", 0) * scale; + data.offsetY = getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = getValue(constraintMap, "scaleY", 0); + data.offsetShearY = getValue(constraintMap, "shearY", 0); + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + data.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX); + data.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (let i = 0; i < root.path.length; i++) { + let constraintMap = root.path[i]; + let data = new PathConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findSlot(targetName); + if (!target) + throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`); + data.target = target; + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.position = getValue(constraintMap, "position", 0); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + skeletonData.pathConstraints.push(data); + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + let skinMap = root.skins[i]; + let skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) { + let boneName = skinMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) { + let constraintName = skinMap.ik[ii]; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) { + let constraintName = skinMap.transform[ii]; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) { + let constraintName = skinMap.path[ii]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (let slotName in skinMap.attachments) { + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); + let slotMap = skinMap.attachments[slotName]; + for (let entryName in slotMap) { + let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) + skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) + throw new Error(`Skin not found: ${linkedMesh.skin}`); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (let eventName in root.events) { + let eventMap = root.events[eventName]; + let data = new EventData(eventName); + data.intValue = getValue(eventMap, "int", 0); + data.floatValue = getValue(eventMap, "float", 0); + data.stringValue = getValue(eventMap, "string", ""); + data.audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + data.volume = getValue(eventMap, "volume", 1); + data.balance = getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (let animationName in root.animations) { + let animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + } + readAttachment(map, skin, slotIndex, name, skeletonData) { + let scale = this.scale; + name = getValue(map, "name", name); + switch (getValue(map, "type", "region")) { + case "region": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + region.sequence = sequence; + let color = getValue(map, "color", null); + if (color) + region.color.setFromString(color); + if (region.region != null) + region.updateRegion(); + return region; + } + case "boundingbox": { + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + this.readVertices(map, box, map.vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + let color = getValue(map, "color", null); + if (color) + mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + mesh.sequence = sequence; + let parent = getValue(map, "parent", null); + if (parent) { + this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true))); + return mesh; + } + let uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + if (mesh.region != null) + mesh.updateRegion(); + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + let vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + let color = getValue(map, "color", null); + if (color) + path.color.setFromString(color); + return path; + } + case "point": { + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + let color = getValue(map, "color", null); + if (color) + point.color.setFromString(color); + return point; + } + case "clipping": { + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + let end = getValue(map, "end", null); + if (end) + clip.endSlot = skeletonData.findSlot(end); + let vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + clip.color.setFromString(color); + return clip; + } + } + return null; + } + readSequence(map) { + if (map == null) + return null; + let sequence = new Sequence(getValue(map, "count", 0)); + sequence.start = getValue(map, "start", 1); + sequence.digits = getValue(map, "digits", 0); + sequence.setupIndex = getValue(map, "setup", 0); + return sequence; + } + readVertices(map, attachment, verticesLength) { + let scale = this.scale; + attachment.worldVerticesLength = verticesLength; + let vertices = map.vertices; + if (verticesLength == vertices.length) { + let scaledVertices = Utils.toFloatArray(vertices); + if (scale != 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + let weights = new Array(); + let bones = new Array(); + for (let i = 0, n = vertices.length; i < n; ) { + let boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + readAnimation(map, name, skeletonData) { + let scale = this.scale; + let timelines = new Array(); + if (map.slots) { + for (let slotName in map.slots) { + let slotMap = map.slots[slotName]; + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error("Slot not found: " + slotName); + let slotIndex = slot.index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + if (!timelineMap) + continue; + let frames = timelineMap.length; + if (timelineName == "attachment") { + let timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + let keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); + } + timelines.push(timeline); + } else if (timelineName == "rgba") { + let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb") { + let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "alpha") { + timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1)); + } else if (timelineName == "rgba2") { + let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb2") { + let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.bones) { + for (let boneName in map.bones) { + let boneMap = map.bones[boneName]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error("Bone not found: " + boneName); + let boneIndex = bone.index; + for (let timelineName in boneMap) { + let timelineMap = boneMap[timelineName]; + let frames = timelineMap.length; + if (frames == 0) + continue; + if (timelineName === "rotate") { + timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1)); + } else if (timelineName === "translate") { + let timeline = new TranslateTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale)); + } else if (timelineName === "translatex") { + let timeline = new TranslateXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "translatey") { + let timeline = new TranslateYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "scale") { + let timeline = new ScaleTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1)); + } else if (timelineName === "scalex") { + let timeline = new ScaleXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "scaley") { + let timeline = new ScaleYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "shear") { + let timeline = new ShearTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1)); + } else if (timelineName === "shearx") { + let timeline = new ShearXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "sheary") { + let timeline = new ShearYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } + } + } + } + if (map.ik) { + for (let constraintName in map.ik) { + let constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error("IK Constraint not found: " + constraintName); + let constraintIndex = skeletonData.ikConstraints.indexOf(constraint); + let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + let nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mix2 = getValue(nextMap, "mix", 1); + let softness2 = getValue(nextMap, "softness", 0) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (let constraintName in map.transform) { + let timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error("Transform constraint not found: " + constraintName); + let constraintIndex = skeletonData.transformConstraints.indexOf(constraint); + let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1); + let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let mixScaleX2 = getValue(nextMap, "mixScaleX", 1); + let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2); + let mixShearY2 = getValue(nextMap, "mixShearY", 1); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (let constraintName in map.path) { + let constraintMap = map.path[constraintName]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error("Path constraint not found: " + constraintName); + let constraintIndex = skeletonData.pathConstraints.indexOf(constraint); + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName === "position") { + let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1)); + } else if (timelineName === "spacing") { + let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1)); + } else if (timelineName === "mix") { + let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.attachments) { + for (let attachmentsName in map.attachments) { + let attachmentsMap = map.attachments[attachmentsName]; + let skin = skeletonData.findSkin(attachmentsName); + if (!skin) + throw new Error("Skin not found: " + attachmentsName); + for (let slotMapName in attachmentsMap) { + let slotMap = attachmentsMap[slotMapName]; + let slot = skeletonData.findSlot(slotMapName); + if (!slot) + throw new Error("Slot not found: " + slotMapName); + let slotIndex = slot.index; + for (let attachmentMapName in slotMap) { + let attachmentMap = slotMap[attachmentMapName]; + let attachment = skin.getAttachment(slotIndex, attachmentMapName); + for (let timelineMapName in attachmentMap) { + let timelineMap = attachmentMap[timelineMapName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + if (timelineMapName == "deform") { + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let curve = keyMap.curve; + if (curve) + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineMapName == "sequence") { + let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment); + let lastDelay = 0; + for (let frame = 0; frame < timelineMap.length; frame++) { + let delay = getValue(keyMap, "delay", lastDelay); + let time = getValue(keyMap, "time", 0); + let mode = SequenceMode[getValue(keyMap, "mode", "hold")]; + let index = getValue(keyMap, "index", 0); + timeline.setFrame(frame, time, mode, index, delay); + lastDelay = delay; + keyMap = timelineMap[frame + 1]; + } + timelines.push(timeline); + } + } + } + } + } + } + if (map.drawOrder) { + let timeline = new DrawOrderTimeline(map.drawOrder.length); + let slotCount = skeletonData.slots.length; + let frame = 0; + for (let i = 0; i < map.drawOrder.length; i++, frame++) { + let drawOrderMap = map.drawOrder[i]; + let drawOrder = null; + let offsets = getValue(drawOrderMap, "offsets", null); + if (offsets) { + drawOrder = Utils.newArray(slotCount, -1); + let unchanged = Utils.newArray(slotCount - offsets.length, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsets.length; ii++) { + let offsetMap = offsets[ii]; + let slot = skeletonData.findSlot(offsetMap.slot); + if (!slot) + throw new Error("Slot not found: " + slot); + let slotIndex = slot.index; + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + } + if (map.events) { + let timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + let eventMap = map.events[i]; + let eventData = skeletonData.findEvent(eventMap.name); + if (!eventData) + throw new Error("Event not found: " + eventMap.name); + let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + event.intValue = getValue(eventMap, "int", eventData.intValue); + event.floatValue = getValue(eventMap, "float", eventData.floatValue); + event.stringValue = getValue(eventMap, "string", eventData.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", 1); + event.balance = getValue(eventMap, "balance", 0); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + skeletonData.animations.push(new Animation(name, timelines, duration)); + } + }; + var LinkedMesh2 = class { + parent; + skin; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + function readTimeline12(keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value = getValue(keyMap, "value", defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let value2 = getValue(nextMap, "value", defaultValue) * scale; + if (keyMap.curve) + bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + } + function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value1 = getValue(keyMap, name1, defaultValue) * scale; + let value2 = getValue(keyMap, name2, defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; + let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + } + function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve == "stepped") { + timeline.setStepped(frame); + return bezier; + } + let i = value << 2; + let cx1 = curve[i]; + let cy1 = curve[i + 1] * scale; + let cx2 = curve[i + 2]; + let cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; + } + function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; + } + + // spine-core/src/polyfills.ts + (() => { + if (typeof Math.fround === "undefined") { + Math.fround = function(array) { + return function(x) { + return array[0] = x, array[0]; + }; + }(new Float32Array(1)); + } + })(); + + // spine-canvas/src/CanvasTexture.ts + var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-canvas/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new CanvasTexture(image); + }, pathPrefix, downloader); + } + }; + + // spine-canvas/src/SkeletonRenderer.ts + var worldVertices = Utils.newFloatArray(8); + var _SkeletonRenderer = class { + ctx; + triangleRendering = false; + debugRendering = false; + vertices = Utils.newFloatArray(8 * 1024); + tempColor = new Color(); + constructor(context) { + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + } + drawImages(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let bone = slot.bone; + if (!bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof RegionAttachment)) + continue; + attachment.computeWorldVertices(slot, worldVertices, 0, 2); + let region = attachment.region; + let image = region.texture.getImage(); + let slotColor = slot.color; + let regionColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * regionColor.r, + skeletonColor.g * slotColor.g * regionColor.g, + skeletonColor.b * slotColor.b * regionColor.b, + skeletonColor.a * slotColor.a * regionColor.a + ); + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + let 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; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let attachment = slot.getAttachment(); + let texture; + let region; + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + texture = regionAttachment.region.texture.getImage(); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.texture.getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode != blendMode) + blendMode = slot.data.blendMode; + let slotColor = slot.color; + let attachmentColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * attachmentColor.r, + skeletonColor.g * slotColor.g * attachmentColor.g, + skeletonColor.b * slotColor.b * attachmentColor.b, + skeletonColor.a * slotColor.a * attachmentColor.a + ); + 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; + 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]; + this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + // Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 + // Apache 2 licensed + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + let ctx = this.ctx; + u0 *= img.width; + v0 *= img.height; + u1 *= img.width; + v1 *= img.height; + u2 *= img.width; + v2 *= img.height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = region.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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 + ); + region.computeWorldVertices(slot, this.vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let vertices = this.vertices; + let uvs = region.uvs; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = mesh.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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; + let vertices = this.vertices; + if (vertices.length < mesh.worldVerticesLength) + this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let uvs = mesh.uvs; + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } + }; + var SkeletonRenderer = _SkeletonRenderer; + __publicField(SkeletonRenderer, "QUAD_TRIANGLES", [0, 1, 2, 2, 3, 0]); + __publicField(SkeletonRenderer, "VERTEX_SIZE", 2 + 2 + 4); + return __toCommonJS(src_exports); +})(); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/lib/4.2/spine-canvas.js b/release/MAC版本/lib/4.2/spine-canvas.js new file mode 100644 index 0000000..2dbc1f7 --- /dev/null +++ b/release/MAC版本/lib/4.2/spine-canvas.js @@ -0,0 +1,11714 @@ +"use strict"; +var spine = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // spine-canvas/src/index.ts + var index_exports = {}; + __export(index_exports, { + AlphaTimeline: () => AlphaTimeline, + Animation: () => Animation, + AnimationState: () => AnimationState, + AnimationStateAdapter: () => AnimationStateAdapter, + AnimationStateData: () => AnimationStateData, + AssetCache: () => AssetCache, + AssetManager: () => AssetManager, + AssetManagerBase: () => AssetManagerBase, + AtlasAttachmentLoader: () => AtlasAttachmentLoader, + Attachment: () => Attachment, + AttachmentTimeline: () => AttachmentTimeline, + BinaryInput: () => BinaryInput, + BlendMode: () => BlendMode, + Bone: () => Bone, + BoneData: () => BoneData, + BoundingBoxAttachment: () => BoundingBoxAttachment, + CURRENT: () => CURRENT, + CanvasTexture: () => CanvasTexture, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + ConstraintData: () => ConstraintData, + CurveTimeline: () => CurveTimeline, + CurveTimeline1: () => CurveTimeline1, + CurveTimeline2: () => CurveTimeline2, + DebugUtils: () => DebugUtils, + DeformTimeline: () => DeformTimeline, + Downloader: () => Downloader, + DrawOrderTimeline: () => DrawOrderTimeline, + Event: () => Event, + EventData: () => EventData, + EventQueue: () => EventQueue, + EventTimeline: () => EventTimeline, + EventType: () => EventType, + FIRST: () => FIRST, + FakeTexture: () => FakeTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + Inherit: () => Inherit, + InheritTimeline: () => InheritTimeline, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + MathUtils: () => MathUtils, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + Physics: () => Physics, + PhysicsConstraintDampingTimeline: () => PhysicsConstraintDampingTimeline, + PhysicsConstraintGravityTimeline: () => PhysicsConstraintGravityTimeline, + PhysicsConstraintInertiaTimeline: () => PhysicsConstraintInertiaTimeline, + PhysicsConstraintMassTimeline: () => PhysicsConstraintMassTimeline, + PhysicsConstraintMixTimeline: () => PhysicsConstraintMixTimeline, + PhysicsConstraintResetTimeline: () => PhysicsConstraintResetTimeline, + PhysicsConstraintStrengthTimeline: () => PhysicsConstraintStrengthTimeline, + PhysicsConstraintTimeline: () => PhysicsConstraintTimeline, + PhysicsConstraintWindTimeline: () => PhysicsConstraintWindTimeline, + PointAttachment: () => PointAttachment, + Pool: () => Pool, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + SequenceTimeline: () => SequenceTimeline, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + StringSet: () => StringSet, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + VertexAttachment: () => VertexAttachment, + WindowedMean: () => WindowedMean + }); + + // spine-core/src/Utils.ts + var IntSet = class { + array = new Array(); + add(value) { + let contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] != void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } + }; + var StringSet = class { + entries = {}; + size = 0; + add(value) { + let contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + let oldSize = this.size; + for (var i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize != this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } + }; + var Color = class _Color { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + static WHITE = new _Color(1, 1, 1, 1); + static RED = new _Color(1, 0, 0, 1); + static GREEN = new _Color(0, 1, 0, 1); + static BLUE = new _Color(0, 0, 1, 1); + static MAGENTA = new _Color(1, 0, 1, 1); + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) == "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) this.r = 0; + else if (this.r > 1) this.r = 1; + if (this.g < 0) this.g = 0; + else if (this.g > 1) this.g = 1; + if (this.b < 0) this.b = 0; + else if (this.b > 1) this.b = 1; + if (this.a < 0) this.a = 0; + else if (this.a > 1) this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + toRgb888() { + const hex = (x) => ("0" + (x * 255).toString(16)).slice(-2); + return Number("0x" + hex(this.r) + hex(this.g) + hex(this.b)); + } + static fromString(hex, color = new _Color()) { + return color.setFromString(hex); + } + }; + var MathUtils = class _MathUtils { + static PI = 3.1415927; + static PI2 = _MathUtils.PI * 2; + static invPI2 = 1 / _MathUtils.PI2; + static radiansToDegrees = 180 / _MathUtils.PI; + static radDeg = _MathUtils.radiansToDegrees; + static degreesToRadians = _MathUtils.PI / 180; + static degRad = _MathUtils.degreesToRadians; + static clamp(value, min, max) { + if (value < min) return min; + if (value > max) return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static atan2Deg(y, x) { + return Math.atan2(y, x) * _MathUtils.degRad; + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + let u = Math.random(); + let d = max - min; + if (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } + }; + var Interpolation = class { + apply(start, end, a) { + return start + (end - start) * this.applyInternal(a); + } + }; + var Pow = class extends Interpolation { + power = 2; + constructor(power) { + super(); + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + } + }; + var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + } + }; + var Utils = class _Utils { + static SUPPORTS_TYPED_ARRAYS = typeof Float32Array !== "undefined"; + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + static setArraySize(array, size, value = 0) { + let oldSize = array.length; + if (oldSize == size) return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) array[i] = value; + } + return array; + } + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + let array = new Array(size); + for (let i = 0; i < size; i++) array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + // This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109 + static webkit602BugfixHelper(alpha, blend) { + } + static contains(array, element, identity = true) { + for (var i = 0; i < array.length; i++) + if (array[i] == element) return true; + return false; + } + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } + }; + var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + let bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + } + }; + var Pool = class { + items = new Array(); + instantiator; + constructor(instantiator) { + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + if (item.reset) item.reset(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } + }; + var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + let x = this.x; + let y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + let len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + } + }; + var TimeKeeper = class { + maxDelta = 0.064; + framesPerSecond = 0; + delta = 0; + totalTime = 0; + lastTime = Date.now() / 1e3; + frameCount = 0; + frameTime = 0; + update() { + let now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } + }; + var WindowedMean = class { + values; + addedValues = 0; + lastValue = 0; + mean = 0; + dirty = true; + constructor(windowSize = 32) { + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } + }; + + // spine-core/src/attachments/Attachment.ts + var Attachment = class { + name; + constructor(name) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + } + }; + var VertexAttachment = class _VertexAttachment extends Attachment { + static nextID = 0; + /** The unique ID for this attachment. */ + id = _VertexAttachment.nextID++; + /** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting + * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null + * if this attachment has no weights. */ + bones = null; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting + * each vertex. */ + vertices = []; + /** The maximum number of world vertex values that can be output by + * {@link #computeWorldVertices()} using the `count` parameter. */ + worldVerticesLength = 0; + /** Timelines for the timeline attachment are also applied to this attachment. + * May be null if no attachment-specific timelines should be applied. */ + timelineAttachment = this; + constructor(name) { + super(name); + } + /** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is + * not empty, it is used to deform the vertices. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. + * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`. + * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * + * `stride` / 2. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + count = offset + (count >> 1) * stride; + let skeleton = slot.bone.skeleton; + let deformArray = slot.deform; + let vertices = this.vertices; + let bones = this.bones; + if (!bones) { + if (deformArray.length > 0) vertices = deformArray; + let bone = slot.bone; + let x = bone.worldX; + let y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + let vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices2[w] = vx * a + vy * b + x; + worldVertices2[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + let n = bones[v]; + v += n + 1; + skip += n; + } + let skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } else { + let deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } + } + /** Does not copy id (generated) or name (set on construction). **/ + copyTo(attachment) { + if (this.bones) { + attachment.bones = new Array(this.bones.length); + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + } + }; + + // spine-core/src/attachments/Sequence.ts + var Sequence = class _Sequence { + static _nextID = 0; + id = _Sequence.nextID(); + regions; + start = 0; + digits = 0; + /** The index of the region to show for the setup pose. */ + setupIndex = 0; + constructor(count) { + this.regions = new Array(count); + } + copy() { + let copy = new _Sequence(this.regions.length); + Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length); + copy.start = this.start; + copy.digits = this.digits; + copy.setupIndex = this.setupIndex; + return copy; + } + apply(slot, attachment) { + let index = slot.sequenceIndex; + if (index == -1) index = this.setupIndex; + if (index >= this.regions.length) index = this.regions.length - 1; + let region = this.regions[index]; + if (attachment.region != region) { + attachment.region = region; + attachment.updateRegion(); + } + } + getPath(basePath, index) { + let result = basePath; + let frame = (this.start + index).toString(); + for (let i = this.digits - frame.length; i > 0; i--) + result += "0"; + result += frame; + return result; + } + static nextID() { + return _Sequence._nextID++; + } + }; + var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => { + SequenceMode2[SequenceMode2["hold"] = 0] = "hold"; + SequenceMode2[SequenceMode2["once"] = 1] = "once"; + SequenceMode2[SequenceMode2["loop"] = 2] = "loop"; + SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong"; + SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse"; + SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse"; + SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse"; + return SequenceMode2; + })(SequenceMode || {}); + var SequenceModeValues = [ + 0 /* hold */, + 1 /* once */, + 2 /* loop */, + 3 /* pingpong */, + 4 /* onceReverse */, + 5 /* loopReverse */, + 6 /* pingpongReverse */ + ]; + + // spine-core/src/Animation.ts + var Animation = class { + /** The animation's name, which is unique across all animations in the skeleton. */ + name; + timelines = []; + timelineIds = new StringSet(); + /** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */ + duration; + constructor(name, timelines, duration) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + this.setTimelines(timelines); + this.duration = duration; + } + setTimelines(timelines) { + if (!timelines) throw new Error("timelines cannot be null."); + this.timelines = timelines; + this.timelineIds.clear(); + for (var i = 0; i < timelines.length; i++) + this.timelineIds.addAll(timelines[i].getPropertyIds()); + } + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) return true; + return false; + } + /** Applies all the animation's timelines to the specified skeleton. + * + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. + * @param loop If true, the animation repeats after {@link #getDuration()}. + * @param events May be null to ignore fired events. */ + apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (!skeleton) throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) lastTime %= this.duration; + } + let timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + } + }; + var MixBlend = /* @__PURE__ */ ((MixBlend2) => { + MixBlend2[MixBlend2["setup"] = 0] = "setup"; + MixBlend2[MixBlend2["first"] = 1] = "first"; + MixBlend2[MixBlend2["replace"] = 2] = "replace"; + MixBlend2[MixBlend2["add"] = 3] = "add"; + return MixBlend2; + })(MixBlend || {}); + var MixDirection = /* @__PURE__ */ ((MixDirection2) => { + MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn"; + MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut"; + return MixDirection2; + })(MixDirection || {}); + var Property = { + rotate: 0, + x: 1, + y: 2, + scaleX: 3, + scaleY: 4, + shearX: 5, + shearY: 6, + inherit: 7, + rgb: 8, + alpha: 9, + rgb2: 10, + attachment: 11, + deform: 12, + event: 13, + drawOrder: 14, + ikConstraint: 15, + transformConstraint: 16, + pathConstraintPosition: 17, + pathConstraintSpacing: 18, + pathConstraintMix: 19, + physicsConstraintInertia: 20, + physicsConstraintStrength: 21, + physicsConstraintDamping: 22, + physicsConstraintMass: 23, + physicsConstraintWind: 24, + physicsConstraintGravity: 25, + physicsConstraintMix: 26, + physicsConstraintReset: 27, + sequence: 28 + }; + var Timeline = class { + propertyIds; + frames; + constructor(frameCount, propertyIds) { + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + getFrameEntries() { + return 1; + } + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + static search1(frames, time) { + let n = frames.length; + for (let i = 1; i < n; i++) + if (frames[i] > time) return i - 1; + return n - 1; + } + static search(frames, time, step) { + let n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) return i - step; + return n - step; + } + }; + var CurveTimeline = class extends Timeline { + curves; + // type, x, y, ... + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + this.curves = Utils.newFloatArray( + frameCount + bezierCount * 18 + /*BEZIER_SIZE*/ + ); + this.curves[frameCount - 1] = 1; + } + /** Sets the specified key frame to linear interpolation. */ + setLinear(frame) { + this.curves[frame] = 0; + } + /** Sets the specified key frame to stepped interpolation. */ + setStepped(frame) { + this.curves[frame] = 1; + } + /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger + * than the actual number of Bezier curves. */ + shrink(bezierCount) { + let size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + let newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than + * one curve per frame. + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified + * in the constructor), inclusive. + * @param frame Between 0 and frameCount - 1, inclusive. + * @param value The index of the value for this frame that this curve is used for. + * @param time1 The time for the first key. + * @param value1 The value for the first key. + * @param cx1 The time for the first Bezier handle. + * @param cy1 The value for the first Bezier handle. + * @param cx2 The time of the second Bezier handle. + * @param cy2 The value for the second Bezier handle. + * @param time2 The time for the second key. + * @param value2 The value for the second key. */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + /** Returns the Bezier interpolated value for the specified time. + * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time. + * @param valueOffset The offset from frameIndex to the value this curve is used for. + * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ + getBezierValue(time, frameIndex, valueOffset, i) { + let curves = this.curves; + if (curves[i] > time) { + let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + let x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } + }; + var CurveTimeline1 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, [propertyId]); + } + getFrameEntries() { + return 2; + } + /** Sets the time and value for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE*/ + ] = value; + } + /** Returns the interpolated value for the specified time. */ + getCurveValue(time) { + let frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + let curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: + let before = frames[i], value = frames[ + i + 1 + /*VALUE*/ + ]; + return value + (time - before) / (frames[ + i + 2 + /*ENTRIES*/ + ] - before) * (frames[ + i + 2 + 1 + /*VALUE*/ + ] - value); + case 1: + return frames[ + i + 1 + /*VALUE*/ + ]; + } + return this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + } + getRelativeValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + return setup + value * alpha; + case 1 /* first */: + case 2 /* replace */: + value += setup - current; + } + return current + value * alpha; + } + getAbsoluteValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + if (blend == 0 /* setup */) return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getAbsoluteValue2(time, alpha, blend, current, setup, value) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + if (blend == 0 /* setup */) return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getScaleValue(time, alpha, blend, direction, current, setup) { + const frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time) * setup; + if (alpha == 1) { + if (blend == 3 /* add */) return current + value - setup; + return value; + } + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; + case 1 /* first */: + case 2 /* replace */: + return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha; + } + } else { + let s = 0; + switch (blend) { + case 0 /* setup */: + s = Math.abs(setup) * MathUtils.signum(value); + return s + (value - s) * alpha; + case 1 /* first */: + case 2 /* replace */: + s = Math.abs(current) * MathUtils.signum(value); + return s + (value - s) * alpha; + } + } + return current + (value - setup) * alpha; + } + }; + var CurveTimeline2 = class extends CurveTimeline { + /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + constructor(frameCount, bezierCount, propertyId1, propertyId2) { + super(frameCount, bezierCount, [propertyId1, propertyId2]); + } + getFrameEntries() { + return 3; + } + /** Sets the time and values for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE1*/ + ] = value1; + this.frames[ + frame + 2 + /*VALUE2*/ + ] = value2; + } + }; + var RotateTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.rotate + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.rotation = this.getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + } + }; + var TranslateTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.x + "|" + boneIndex, + Property.y + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case 1 /* first */: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3 /* add */: + bone.x += x * alpha; + bone.y += y * alpha; + } + } + }; + var TranslateXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.x = this.getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + } + }; + var TranslateYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.y + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.y = this.getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + } + }; + var ScaleTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.scaleX + "|" + boneIndex, + Property.scaleY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case 1 /* first */: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let x, y; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + x *= bone.data.scaleX; + y *= bone.data.scaleY; + if (alpha == 1) { + if (blend == 3 /* add */) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } else { + bone.scaleX = x; + bone.scaleY = y; + } + } else { + let bx = 0, by = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ScaleXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.scaleX = this.getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + } + }; + var ScaleYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.scaleY = this.getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + } + }; + var ShearTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.shearX + "|" + boneIndex, + Property.shearY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case 1 /* first */: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3 /* add */: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + } + }; + var ShearXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.shearX = this.getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + } + }; + var ShearYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) bone.shearY = this.getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + } + }; + var InheritTimeline = class extends Timeline { + boneIndex = 0; + constructor(frameCount, boneIndex) { + super(frameCount, [Property.inherit + "|" + boneIndex]); + this.boneIndex = boneIndex; + } + getFrameEntries() { + return 2; + } + /** Sets the transform mode for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, inherit) { + frame *= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*INHERIT*/ + ] = inherit; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) bone.inherit = bone.data.inherit; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) bone.inherit = bone.data.inherit; + return; + } + bone.inherit = this.frames[ + Timeline.search( + frames, + time, + 2 + /*ENTRIES*/ + ) + 1 + /*INHERIT*/ + ]; + } + }; + var RGBATimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 5; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.setFromColor(setup); + return; + case 1 /* first */: + color.add( + (setup.r - color.r) * alpha, + (setup.g - color.g) * alpha, + (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha + ); + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + let i = Timeline.search( + frames, + time, + 5 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 5 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + let t = (time - before) / (frames[ + i + 5 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 5 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 5 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 5 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 5 + 4 + /*A*/ + ] - a) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == 0 /* setup */) color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } + }; + var RGBTimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 4; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + return; + case 1 /* first */: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 4 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 4 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 4 + 3 + /*B*/ + ] - b) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + color.r = r; + color.g = g; + color.b = b; + } else { + if (blend == 0 /* setup */) { + let setup = slot.data.color; + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + } + color.r += (r - color.r) * alpha; + color.g += (g - color.g) * alpha; + color.b += (b - color.b) * alpha; + } + } + }; + var AlphaTimeline = class extends CurveTimeline1 { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let color = slot.color; + if (time < this.frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.a = setup.a; + return; + case 1 /* first */: + color.a += (setup.a - color.a) * alpha; + } + return; + } + let a = this.getCurveValue(time); + if (alpha == 1) + color.a = a; + else { + if (blend == 0 /* setup */) color.a = slot.data.color.a; + color.a += (a - color.a) * alpha; + } + } + }; + var RGBA2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 8; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + this.frames[ + frame + 5 + /*R2*/ + ] = r2; + this.frames[ + frame + 6 + /*G2*/ + ] = g2; + this.frames[ + frame + 7 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.add( + (setupLight.r - light.r) * alpha, + (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha + ); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 8 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 8 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 8 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 8 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 8 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 8 + 4 + /*A*/ + ] - a) * t; + r2 += (frames[ + i + 8 + 5 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 8 + 6 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 8 + 7 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 7, + curveType + 18 * 6 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.set(r, g, b, a); + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + light.setFromColor(slot.data.color); + let setupDark = slot.data.darkColor; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var RGB2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 7; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*R2*/ + ] = r2; + this.frames[ + frame + 5 + /*G2*/ + ] = g2; + this.frames[ + frame + 6 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 7 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 7 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 7 + 3 + /*B*/ + ] - b) * t; + r2 += (frames[ + i + 7 + 4 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 7 + 5 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 7 + 6 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.r = r; + light.g = g; + light.b = b; + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.r += (r - light.r) * alpha; + light.g += (g - light.g) * alpha; + light.b += (b - light.b) * alpha; + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var AttachmentTimeline = class extends Timeline { + slotIndex = 0; + /** The attachment name for each key frame. May contain null values to clear the attachment. */ + attachmentNames; + constructor(frameCount, slotIndex) { + super(frameCount, [ + Property.attachment + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the attachment name for the specified key frame. */ + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]); + } + setAttachment(skeleton, slot, attachmentName) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } + }; + var DeformTimeline = class extends CurveTimeline { + slotIndex = 0; + /** The attachment that will be deformed. */ + attachment; + /** The vertices for each key frame. */ + vertices; + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, [ + Property.deform + "|" + slotIndex + "|" + attachment.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the vertices for the specified key frame. + * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + /** @param value1 Ignored (0 is used for a deform timeline). + * @param value2 Ignored (1 is used for a deform timeline). */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + let curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: + let x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + let x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + let x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let slotAttachment = slot.getAttachment(); + if (!slotAttachment) return; + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment) return; + let deform = slot.deform; + if (deform.length == 0) blend = 0 /* setup */; + let vertices = this.vertices; + let vertexCount = vertices[0].length; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + deform.length = 0; + return; + case 1 /* first */: + if (alpha == 1) { + deform.length = 0; + return; + } + deform.length = vertexCount; + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + return; + } + deform.length = vertexCount; + if (time >= frames[frames.length - 1]) { + let lastVertices = vertices[frames.length - 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] - setupVertices[i2]; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2]; + } + } else + Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let setup = setupVertices[i2]; + deform[i2] = setup + (lastVertices[i2] - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] = lastVertices[i2] * alpha; + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - deform[i2]) * alpha; + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] * alpha; + } + } + } + return; + } + let frame = Timeline.search1(frames, time); + let percent = this.getCurvePercent(time, frame); + let prevVertices = vertices[frame]; + let nextVertices = vertices[frame + 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2], setup = setupVertices[i2]; + deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha; + } + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + } + } + } + }; + var EventTimeline = class _EventTimeline extends Timeline { + static propertyIds = ["" + Property.event]; + /** The event for each key frame. */ + events; + constructor(frameCount) { + super(frameCount, _EventTimeline.propertyIds); + this.events = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the event for the specified key frame. */ + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + /** Fires events for frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (!firedEvents) return; + let frames = this.frames; + let frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search1(frames, lastTime) + 1; + let frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] != frameTime) break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } + }; + var DrawOrderTimeline = class _DrawOrderTimeline extends Timeline { + static propertyIds = ["" + Property.drawOrder]; + /** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */ + drawOrders; + constructor(frameCount) { + super(frameCount, _DrawOrderTimeline.propertyIds); + this.drawOrders = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the draw order for the specified key frame. + * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose + * draw order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + let idx = Timeline.search1(this.frames, time); + let drawOrderToSetupIndex = this.drawOrders[idx]; + if (!drawOrderToSetupIndex) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + else { + let drawOrder = skeleton.drawOrder; + let slots = skeleton.slots; + for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } + }; + var IkConstraintTimeline = class extends CurveTimeline { + /** The index of the IK constraint in {@link Skeleton#getIkConstraints()} that will be changed when this timeline is applied */ + constraintIndex = 0; + constructor(frameCount, bezierCount, ikConstraintIndex) { + super(frameCount, bezierCount, [ + Property.ikConstraint + "|" + ikConstraintIndex + ]); + this.constraintIndex = ikConstraintIndex; + } + getFrameEntries() { + return 6; + } + /** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */ + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*MIX*/ + ] = mix; + this.frames[ + frame + 2 + /*SOFTNESS*/ + ] = softness; + this.frames[ + frame + 3 + /*BEND_DIRECTION*/ + ] = bendDirection; + this.frames[ + frame + 4 + /*COMPRESS*/ + ] = compress ? 1 : 0; + this.frames[ + frame + 5 + /*STRETCH*/ + ] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.ikConstraints[this.constraintIndex]; + if (!constraint.active) return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case 1 /* first */: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + let mix = 0, softness = 0; + let i = Timeline.search( + frames, + time, + 6 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 6 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + let t = (time - before) / (frames[ + i + 6 + /*ENTRIES*/ + ] - before); + mix += (frames[ + i + 6 + 1 + /*MIX*/ + ] - mix) * t; + softness += (frames[ + i + 6 + 2 + /*SOFTNESS*/ + ] - softness) * t; + break; + case 1: + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + break; + default: + mix = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + softness = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (direction == 1 /* mixOut */) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } else { + constraint.mix += (mix - constraint.mix) * alpha; + constraint.softness += (softness - constraint.softness) * alpha; + if (direction == 0 /* mixIn */) { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } + } + }; + var TransformConstraintTimeline = class extends CurveTimeline { + /** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, transformConstraintIndex) { + super(frameCount, bezierCount, [ + Property.transformConstraint + "|" + transformConstraintIndex + ]); + this.constraintIndex = transformConstraintIndex; + } + getFrameEntries() { + return 7; + } + /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */ + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + let frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + frames[ + frame + 4 + /*SCALEX*/ + ] = mixScaleX; + frames[ + frame + 5 + /*SCALEY*/ + ] = mixScaleY; + frames[ + frame + 6 + /*SHEARY*/ + ] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.transformConstraints[this.constraintIndex]; + if (!constraint.active) return; + let frames = this.frames; + if (time < frames[0]) { + let data = constraint.data; + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + return; + case 1 /* first */: + constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (data.mixX - constraint.mixX) * alpha; + constraint.mixY += (data.mixY - constraint.mixY) * alpha; + constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 7 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 7 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 7 + 3 + /*Y*/ + ] - y) * t; + scaleX += (frames[ + i + 7 + 4 + /*SCALEX*/ + ] - scaleX) * t; + scaleY += (frames[ + i + 7 + 5 + /*SCALEY*/ + ] - scaleY) * t; + shearY += (frames[ + i + 7 + 6 + /*SHEARY*/ + ] - shearY) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + scaleX = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + scaleY = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + shearY = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; + constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; + constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + } + } + }; + var PathConstraintPositionTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.position = this.getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position); + } + }; + var PathConstraintSpacingTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.spacing = this.getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing); + } + }; + var PathConstraintMixTimeline = class extends CurveTimeline { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, [ + Property.pathConstraintMix + "|" + pathConstraintIndex + ]); + this.constraintIndex = pathConstraintIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, mixRotate, mixX, mixY) { + let frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (!constraint.active) return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = constraint.data.mixRotate; + constraint.mixX = constraint.data.mixX; + constraint.mixY = constraint.data.mixY; + return; + case 1 /* first */: + constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha; + constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha; + } + return; + } + let rotate, x, y; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 4 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 4 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 4 + 3 + /*Y*/ + ] - y) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + } + } + }; + var PhysicsConstraintTimeline = class extends CurveTimeline1 { + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline + * is applied, or -1 if all physics constraints in the skeleton will be changed. */ + constraintIndex = 0; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, bezierCount, physicsConstraintIndex, property) { + super(frameCount, bezierCount, property + "|" + physicsConstraintIndex); + this.constraintIndex = physicsConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex == -1) { + const value = time >= this.frames[0] ? this.getCurveValue(time) : 0; + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active && this.global(constraint2.data)) + this.set(constraint2, this.getAbsoluteValue2(time, alpha, blend, this.get(constraint2), this.setup(constraint2), value)); + } + } else { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (constraint.active) this.set(constraint, this.getAbsoluteValue(time, alpha, blend, this.get(constraint), this.setup(constraint))); + } + } + }; + var PhysicsConstraintInertiaTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); + } + setup(constraint) { + return constraint.data.inertia; + } + get(constraint) { + return constraint.inertia; + } + set(constraint, value) { + constraint.inertia = value; + } + global(constraint) { + return constraint.inertiaGlobal; + } + }; + var PhysicsConstraintStrengthTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); + } + setup(constraint) { + return constraint.data.strength; + } + get(constraint) { + return constraint.strength; + } + set(constraint, value) { + constraint.strength = value; + } + global(constraint) { + return constraint.strengthGlobal; + } + }; + var PhysicsConstraintDampingTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); + } + setup(constraint) { + return constraint.data.damping; + } + get(constraint) { + return constraint.damping; + } + set(constraint, value) { + constraint.damping = value; + } + global(constraint) { + return constraint.dampingGlobal; + } + }; + var PhysicsConstraintMassTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); + } + setup(constraint) { + return 1 / constraint.data.massInverse; + } + get(constraint) { + return 1 / constraint.massInverse; + } + set(constraint, value) { + constraint.massInverse = 1 / value; + } + global(constraint) { + return constraint.massGlobal; + } + }; + var PhysicsConstraintWindTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); + } + setup(constraint) { + return constraint.data.wind; + } + get(constraint) { + return constraint.wind; + } + set(constraint, value) { + constraint.wind = value; + } + global(constraint) { + return constraint.windGlobal; + } + }; + var PhysicsConstraintGravityTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); + } + setup(constraint) { + return constraint.data.gravity; + } + get(constraint) { + return constraint.gravity; + } + set(constraint, value) { + constraint.gravity = value; + } + global(constraint) { + return constraint.gravityGlobal; + } + }; + var PhysicsConstraintMixTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); + } + setup(constraint) { + return constraint.data.mix; + } + get(constraint) { + return constraint.mix; + } + set(constraint, value) { + constraint.mix = value; + } + global(constraint) { + return constraint.mixGlobal; + } + }; + var PhysicsConstraintResetTimeline = class _PhysicsConstraintResetTimeline extends Timeline { + static propertyIds = [Property.physicsConstraintReset.toString()]; + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ + constraintIndex; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, physicsConstraintIndex) { + super(frameCount, _PhysicsConstraintResetTimeline.propertyIds); + this.constraintIndex = physicsConstraintIndex; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ + setFrame(frame, time) { + this.frames[frame] = time; + } + /** Resets the physics constraint when frames > lastTime and <= time. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex != -1) { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (!constraint.active) return; + } + const frames = this.frames; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frames.length - 1]) + return; + if (time < frames[0]) return; + if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) { + if (constraint != null) + constraint.reset(); + else { + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active) constraint2.reset(); + } + } + } + } + }; + var SequenceTimeline = class _SequenceTimeline extends Timeline { + static ENTRIES = 3; + static MODE = 1; + static DELAY = 2; + slotIndex; + attachment; + constructor(frameCount, slotIndex, attachment) { + super(frameCount, [ + Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + } + getFrameEntries() { + return _SequenceTimeline.ENTRIES; + } + getSlotIndex() { + return this.slotIndex; + } + getAttachment() { + return this.attachment; + } + /** Sets the time, mode, index, and frame time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time Seconds between frames. */ + setFrame(frame, time, mode, index, delay) { + let frames = this.frames; + frame *= _SequenceTimeline.ENTRIES; + frames[frame] = time; + frames[frame + _SequenceTimeline.MODE] = mode | index << 4; + frames[frame + _SequenceTimeline.DELAY] = delay; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + let slotAttachment = slot.attachment; + let attachment = this.attachment; + if (slotAttachment != attachment) { + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment) return; + } + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) slot.sequenceIndex = -1; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) slot.sequenceIndex = -1; + return; + } + let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES); + let before = frames[i]; + let modeAndIndex = frames[i + _SequenceTimeline.MODE]; + let delay = frames[i + _SequenceTimeline.DELAY]; + if (!this.attachment.sequence) return; + let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length; + let mode = SequenceModeValues[modeAndIndex & 15]; + if (mode != 0 /* hold */) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case 1 /* once */: + index = Math.min(count - 1, index); + break; + case 2 /* loop */: + index %= count; + break; + case 3 /* pingpong */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) index = n - index; + break; + } + case 4 /* onceReverse */: + index = Math.max(count - 1 - index, 0); + break; + case 5 /* loopReverse */: + index = count - 1 - index % count; + break; + case 6 /* pingpongReverse */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) index = n - index; + } + } + } + slot.sequenceIndex = index; + } + }; + + // spine-core/src/AnimationState.ts + var AnimationState = class _AnimationState { + static _emptyAnimation = new Animation("", [], 0); + static emptyAnimation() { + return _AnimationState._emptyAnimation; + } + /** The AnimationStateData to look up mix durations. */ + data; + /** The list of tracks that currently have animations, which may contain null entries. */ + tracks = new Array(); + /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + * or faster. Defaults to 1. + * + * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */ + timeScale = 1; + unkeyedState = 0; + events = new Array(); + listeners = new Array(); + queue = new EventQueue(this); + propertyIDs = new StringSet(); + animationsChanged = false; + trackEntryPool = new Pool(() => new TrackEntry()); + constructor(data) { + this.data = data; + } + /** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */ + update(delta) { + delta *= this.timeScale; + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let current = tracks[i]; + if (!current) continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + let nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + /** Returns true when all mixing from entries are complete. */ + updateMixingFrom(to, delta) { + let from = to.mixingFrom; + if (!from) return true; + let finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + /** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + * animation state can be applied to multiple skeletons to pose them identically. + * @returns True if any animations were applied. */ + apply(skeleton) { + if (!skeleton) throw new Error("skeleton cannot be null."); + if (this.animationsChanged) this._animationsChanged(); + let events = this.events; + let tracks = this.tracks; + let applied = false; + for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) { + let current = tracks[i2]; + if (!current || current.delay > 0) continue; + applied = true; + let blend = i2 == 0 ? 1 /* first */ : current.mixBlend; + let alpha = current.alpha; + if (current.mixingFrom) + alpha *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && !current.next) + alpha = 0; + let attachments = alpha >= current.alphaAttachmentThreshold; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + let timelines = current.animation.timelines; + let timelineCount = timelines.length; + if (i2 == 0 && alpha == 1 || blend == 3 /* add */) { + if (i2 == 0) attachments = true; + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(alpha, blend); + var timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, 0 /* mixIn */); + } + } else { + let timelineMode = current.timelineMode; + let shortestRotation = current.shortestRotation; + let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1; + if (firstFrame) current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + let timeline2 = timelines[ii]; + let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */; + if (!shortestRotation && timeline2 instanceof RotateTimeline) { + this.applyRotateTimeline(timeline2, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline2 instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, attachments); + } else { + Utils.webkit602BugfixHelper(alpha, blend); + timeline2.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, 0 /* mixIn */); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton, blend) { + let from = to.mixingFrom; + if (from.mixingFrom) this.applyMixingFrom(from, skeleton, blend); + let mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == 1 /* first */) blend = 0 /* setup */; + } else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) mix = 1; + if (blend != 1 /* first */) blend = from.mixBlend; + } + let attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; + let timelines = from.animation.timelines; + let timelineCount = timelines.length; + let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + if (blend == 3 /* add */) { + for (let i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */); + } else { + let timelineMode = from.timelineMode; + let timelineHoldMix = from.timelineHoldMix; + let shortestRotation = from.shortestRotation; + let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1; + if (firstFrame) from.timelinesRotation.length = timelineCount << 1; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + let timeline = timelines[i]; + let direction = 1 /* mixOut */; + let timelineBlend; + let alpha = 0; + switch (timelineMode[i]) { + case SUBSEQUENT: + if (!drawOrder && timeline instanceof DrawOrderTimeline) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaMix; + break; + case HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case HOLD_FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaHold; + break; + default: + timelineBlend = 0 /* setup */; + let holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (!shortestRotation && timeline instanceof RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold); + else { + Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */) + direction = 0 /* mixIn */; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) return; + if (time < timeline.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } else + this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments); + if (slot.attachmentState <= this.unkeyedState) slot.attachmentState = this.unkeyedState + SETUP; + } + setAttachment(skeleton, slot, attachmentName, attachments) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) slot.attachmentState = this.unkeyedState + CURRENT; + } + applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */); + return; + } + let bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) return; + let frames = timeline.frames; + let r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation; + default: + return; + case 1 /* first */: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } else { + r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation; + r2 = bone.data.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= Math.ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + let loops = lastTotal - lastTotal % 360; + total = diff + loops; + let current = diff >= 0, dir = lastTotal >= 0; + if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) { + if (Math.abs(lastTotal - loops) > 180) { + total += 360 * MathUtils.signum(lastTotal); + dir = current; + } else if (loops != 0) + total -= 360 * MathUtils.signum(lastTotal); + else + dir = current; + } + if (dir != current) total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + let animationStart = entry.animationStart, animationEnd = entry.animationEnd; + let duration = animationEnd - animationStart; + let trackLastWrapped = entry.trackLast % duration; + let events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + let event = events[i]; + if (event.time < trackLastWrapped) break; + if (event.time > animationEnd) continue; + this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) { + if (duration == 0) + complete = true; + else { + const cycles = Math.floor(entry.trackTime / duration); + complete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration); + } + } else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) this.queue.complete(entry); + for (; i < n; i++) { + let event = events[i]; + if (event.time < animationStart) continue; + this.queue.event(entry, event); + } + } + /** Removes all animations from all tracks, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTracks() { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + /** Removes all animations from the track, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTrack(trackIndex) { + if (trackIndex >= this.tracks.length) return; + let current = this.tracks[trackIndex]; + if (!current) return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + let from = entry.mixingFrom; + if (!from) break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setCurrent(index, current, interrupt) { + let from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + if (interrupt) this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + /** Sets an animation by name. + * + * See {@link #setAnimationWith()}. */ + setAnimation(trackIndex, animationName, loop = false) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + } + /** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never + * applied to a skeleton, it is replaced (not mixed from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + setAnimationWith(trackIndex, animation, loop = false) { + if (!animation) throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + let entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + /** Queues an animation by name. + * + * See {@link #addAnimationWith()}. */ + addAnimation(trackIndex, animationName, loop = false, delay = 0) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + } + /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is + * equivalent to calling {@link #setAnimationWith()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix + * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the + * previous entry is looping, its next loop completion is used instead of its duration. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addAnimationWith(trackIndex, animation, loop = false, delay = 0) { + if (!animation) throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + let entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + if (delay < 0) delay = 0; + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) delay = Math.max(delay + last.getTrackComplete() - entry.mixDuration, 0); + } + entry.delay = delay; + return entry; + } + /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()}, + * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still mixes out over one frame. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * {@link #addAnimation()} and on the returned track entry, set the + * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and + * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the + * setup pose value if no lower tracks key the property to the value keyed in the new animation. */ + setEmptyAnimation(trackIndex, mixDuration = 0) { + let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling + * {@link #setEmptyAnimation()}. + * + * See {@link #setEmptyAnimation()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or + * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next + * loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay); + if (delay <= 0) entry.delay = Math.max(entry.delay + entry.mixDuration - mixDuration, 0); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix + * duration. */ + setEmptyAnimations(mixDuration = 0) { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + let current = this.tracks[i]; + if (current) this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + /** @param last May be null. */ + trackEntry(trackIndex, animation, loop, last) { + let entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.reverse = false; + entry.shortestRotation = false; + entry.eventThreshold = 0; + entry.alphaAttachmentThreshold = 0; + entry.mixAttachmentThreshold = 0; + entry.mixDrawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.interruptAlpha = 1; + entry.totalAlpha = 0; + entry.mixBlend = 2 /* replace */; + return entry; + } + /** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */ + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + this.propertyIDs.clear(); + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let entry = tracks[i]; + if (!entry) continue; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + if (!entry.mixingTo || entry.mixBlend != 3 /* add */) this.computeHold(entry); + entry = entry.mixingTo; + } while (entry); + } + } + computeHold(entry) { + let to = entry.mixingTo; + let timelines = entry.animation.timelines; + let timelinesCount = entry.animation.timelines.length; + let timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + let timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + let propertyIDs = this.propertyIDs; + if (to && to.holdPrevious) { + for (let i = 0; i < timelinesCount; i++) + timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; + return; + } + outer: + for (let i = 0; i < timelinesCount; i++) { + let timeline = timelines[i]; + let ids = timeline.getPropertyIds(); + if (!propertyIDs.addAll(ids)) + timelineMode[i] = SUBSEQUENT; + else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) { + timelineMode[i] = FIRST; + } else { + for (let next = to.mixingTo; next; next = next.mixingTo) { + if (next.animation.hasTimeline(ids)) continue; + if (entry.mixDuration > 0) { + timelineMode[i] = HOLD_MIX; + timelineHoldMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = HOLD_FIRST; + } + } + } + /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */ + getCurrent(trackIndex) { + if (trackIndex >= this.tracks.length) return null; + return this.tracks[trackIndex]; + } + /** Adds a listener to receive events for all track entries. */ + addListener(listener) { + if (!listener) throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + /** Removes the listener added with {@link #addListener()}. */ + removeListener(listener) { + let index = this.listeners.indexOf(listener); + if (index >= 0) this.listeners.splice(index, 1); + } + /** Removes all listeners added with {@link #addListener()}. */ + clearListeners() { + this.listeners.length = 0; + } + /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. */ + clearListenerNotifications() { + this.queue.clear(); + } + }; + var TrackEntry = class { + /** The animation to apply for this track entry. */ + animation = null; + previous = null; + /** The animation queued to start after this animation, or null. `next` makes up a linked list. */ + next = null; + /** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */ + mixingFrom = null; + /** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is + * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */ + mixingTo = null; + /** The listener for events generated by this track entry, or null. + * + * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation + * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */ + listener = null; + /** The index of the track where this track entry is either current or queued. + * + * See {@link AnimationState#getCurrent()}. */ + trackIndex = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ + loop = false; + /** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + * of being mixed out. + * + * When mixing between animations that key the same property, if a lower track also keys that property then the value will + * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation + * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + * keys the property, only when a higher track also keys the property. + * + * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the + * previous animation. */ + holdPrevious = false; + reverse = false; + shortestRotation = false; + /** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the + * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event + * timelines are not applied while this animation is being mixed out. */ + eventThreshold = 0; + /** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the + * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to + * 0, so attachment timelines are not applied while this animation is being mixed out. */ + mixAttachmentThreshold = 0; + /** When {@link #getAlpha()} is greater than alphaAttachmentThreshold, attachment timelines are applied. + * Defaults to 0, so attachment timelines are always applied. */ + alphaAttachmentThreshold = 0; + /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the + * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to + * 0, so draw order timelines are not applied while this animation is being mixed out. */ + mixDrawOrderThreshold = 0; + /** Seconds when this animation starts, both initially and after looping. Defaults to 0. + * + * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same + * value to prevent timeline keys before the start time from triggering. */ + animationStart = 0; + /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */ + animationEnd = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and + * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation + * is applied. */ + animationLast = 0; + nextAnimationLast = 0; + /** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay` + * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from + * the start of the previous animation to when this track entry will become the current track entry (ie when the previous + * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`). + * + * {@link #timeScale} affects the delay. */ + delay = 0; + /** Current time in seconds this track entry has been the current track entry. The track time determines + * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting + * looping. */ + trackTime = 0; + trackLast = 0; + nextTrackLast = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation + * abruptly cease being applied. */ + trackEnd = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to + * match the animation speed. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If + * the time scale is not 1, the delay may need to be adjusted. + * + * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */ + timeScale = 0; + /** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults + * to 1, which overwrites the skeleton's current pose with this animation. + * + * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to + * use alpha on track 0 if the skeleton pose is from the last frame render. */ + alpha = 0; + /** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be + * slightly more than `mixDuration` when the mix is complete. */ + mixTime = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData + * {@link AnimationStateData#getMix()} based on the animation before this animation (if any). + * + * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the + * properties it was animating. + * + * The `mixDuration` can be set manually rather than use the value from + * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new + * track entry only before {@link AnimationState#update(float)} is first called. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set + * afterward. */ + _mixDuration = 0; + interruptAlpha = 0; + totalAlpha = 0; + get mixDuration() { + return this._mixDuration; + } + set mixDuration(mixDuration) { + this._mixDuration = mixDuration; + } + setMixDurationWithDelay(mixDuration, delay) { + this._mixDuration = mixDuration; + if (delay <= 0) { + if (this.previous != null) + delay = Math.max(delay + this.previous.getTrackComplete() - mixDuration, 0); + else + delay = 0; + } + this.delay = delay; + } + /** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which + * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to + * the values from the lower tracks. + * + * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first + * called. */ + mixBlend = 2 /* replace */; + timelineMode = new Array(); + timelineHoldMix = new Array(); + timelinesRotation = new Array(); + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + /** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart} + * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the + * `animationStart` time. */ + getAnimationTime() { + if (this.loop) { + let duration = this.animationEnd - this.animationStart; + if (duration == 0) return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + /** Returns true if at least one loop has been completed. + * + * See {@link AnimationStateListener#complete()}. */ + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + /** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + * long way around when using {@link #alpha} and starting animations on other tracks. + * + * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions: + * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long + * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the + * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */ + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + getTrackComplete() { + let duration = this.animationEnd - this.animationStart; + if (duration != 0) { + if (this.loop) return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) return duration; + } + return this.trackTime; + } + /** Returns true if this track entry has been applied at least once. + *

+ * See {@link AnimationState#apply(Skeleton)}. */ + wasApplied() { + return this.nextTrackLast != -1; + } + /** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next + * {@link AnimationState#update(float)}. */ + isNextReady() { + return this.next != null && this.nextTrackLast - this.next.delay >= 0; + } + }; + var EventQueue = class { + objects = []; + drainDisabled = false; + animState; + constructor(animState) { + this.animState = animState; + } + start(entry) { + this.objects.push(0 /* start */); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(1 /* interrupt */); + this.objects.push(entry); + } + end(entry) { + this.objects.push(2 /* end */); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(3 /* dispose */); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(4 /* complete */); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(5 /* event */); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) return; + this.drainDisabled = true; + let objects = this.objects; + for (let i = 0; i < objects.length; i += 2) { + let type = objects[i]; + let entry = objects[i + 1]; + let listeners = this.animState.listeners.slice(); + switch (type) { + case 0 /* start */: + if (entry.listener && entry.listener.start) entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.start) listener.start(entry); + } + break; + case 1 /* interrupt */: + if (entry.listener && entry.listener.interrupt) entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.interrupt) listener.interrupt(entry); + } + break; + case 2 /* end */: + if (entry.listener && entry.listener.end) entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.end) listener.end(entry); + } + // Fall through. + case 3 /* dispose */: + if (entry.listener && entry.listener.dispose) entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.dispose) listener.dispose(entry); + } + this.animState.trackEntryPool.free(entry); + break; + case 4 /* complete */: + if (entry.listener && entry.listener.complete) entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.complete) listener.complete(entry); + } + break; + case 5 /* event */: + let event = objects[i++ + 2]; + if (entry.listener && entry.listener.event) entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.event) listener.event(entry, event); + } + break; + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } + }; + var EventType = /* @__PURE__ */ ((EventType2) => { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + return EventType2; + })(EventType || {}); + var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } + }; + var SUBSEQUENT = 0; + var FIRST = 1; + var HOLD_SUBSEQUENT = 2; + var HOLD_FIRST = 3; + var HOLD_MIX = 4; + var SETUP = 1; + var CURRENT = 2; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + /** The SkeletonData to look up animations when they are specified by name. */ + skeletonData; + animationToMixTime = {}; + /** The mix duration to use when no mix duration has been defined between two animations. */ + defaultMix = 0; + constructor(skeletonData) { + if (!skeletonData) throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + /** Sets a mix duration by animation name. + * + * See {@link #setMixWith()}. */ + setMix(fromName, toName, duration) { + let from = this.skeletonData.findAnimation(fromName); + if (!from) throw new Error("Animation not found: " + fromName); + let to = this.skeletonData.findAnimation(toName); + if (!to) throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + } + /** Sets the mix duration when changing from the specified animation to the other. + * + * See {@link TrackEntry#mixDuration}. */ + setMixWith(from, to, duration) { + if (!from) throw new Error("from cannot be null."); + if (!to) throw new Error("to cannot be null."); + let key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + } + /** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if + * no mix duration has been set. */ + getMix(from, to) { + let key = from.name + "." + to.name; + let value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } + }; + + // spine-core/src/attachments/BoundingBoxAttachment.ts + var BoundingBoxAttachment = class _BoundingBoxAttachment extends VertexAttachment { + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new _BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/ClippingAttachment.ts + var ClippingAttachment = class _ClippingAttachment extends VertexAttachment { + /** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of + * the skeleton's rendering. */ + endSlot = null; + // Nonessential. + /** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons + * are not usually rendered at runtime. */ + color = new Color(0.2275, 0.2275, 0.8078, 1); + // ce3a3aff + constructor(name) { + super(name); + } + copy() { + let copy = new _ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/Texture.ts + var Texture = class { + _image; + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } + }; + var TextureFilter = /* @__PURE__ */ ((TextureFilter3) => { + TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest"; + TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear"; + TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap"; + TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + return TextureFilter3; + })(TextureFilter || {}); + var TextureWrap = /* @__PURE__ */ ((TextureWrap3) => { + TextureWrap3[TextureWrap3["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap3[TextureWrap3["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap3[TextureWrap3["Repeat"] = 10497] = "Repeat"; + return TextureWrap3; + })(TextureWrap || {}); + var TextureRegion = class { + texture; + u = 0; + v = 0; + u2 = 0; + v2 = 0; + width = 0; + height = 0; + degrees = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + }; + var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-core/src/TextureAtlas.ts + var TextureAtlas = class { + pages = new Array(); + regions = new Array(); + constructor(atlasText) { + let reader = new TextureAtlasReader(atlasText); + let entry = new Array(4); + let pageFields = {}; + pageFields["size"] = (page2) => { + page2.width = parseInt(entry[1]); + page2.height = parseInt(entry[2]); + }; + pageFields["format"] = () => { + }; + pageFields["filter"] = (page2) => { + page2.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page2.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields["repeat"] = (page2) => { + if (entry[1].indexOf("x") != -1) page2.uWrap = 10497 /* Repeat */; + if (entry[1].indexOf("y") != -1) page2.vWrap = 10497 /* Repeat */; + }; + pageFields["pma"] = (page2) => { + page2.pma = entry[1] == "true"; + }; + var regionFields = {}; + regionFields["xy"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields["size"] = (region) => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields["bounds"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields["offset"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields["orig"] = (region) => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields["offsets"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields["rotate"] = (region) => { + let value = entry[1]; + if (value == "true") + region.degrees = 90; + else if (value != "false") + region.degrees = parseInt(value); + }; + regionFields["index"] = (region) => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length == 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length == 0) break; + if (reader.readEntry(entry, line) == 0) break; + line = reader.readLine(); + } + let page = null; + let names = null; + let values = null; + while (true) { + if (line === null) break; + if (line.trim().length == 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(line.trim()); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) == 0) break; + let field = pageFields[entry[0]]; + if (field) field(page); + } + this.pages.push(page); + } else { + let region = new TextureAtlasRegion(page, line); + while (true) { + let count = reader.readEntry(entry, line = reader.readLine()); + if (count == 0) break; + let field = regionFields[entry[0]]; + if (field) + field(region); + else { + if (!names) names = []; + if (!values) values = []; + names.push(entry[0]); + let entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth == 0 && region.originalHeight == 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0 && values && values.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees == 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (let page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture?.dispose(); + } + } + }; + var TextureAtlasReader = class { + lines; + index = 0; + constructor(text) { + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) return 0; + line = line.trim(); + if (line.length == 0) return 0; + let colon = line.indexOf(":"); + if (colon == -1) return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + let comma = line.indexOf(",", lastMatch); + if (comma == -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) return 4; + } + } + }; + var TextureAtlasPage = class { + name; + minFilter = 9728 /* Nearest */; + magFilter = 9728 /* Nearest */; + uWrap = 33071 /* ClampToEdge */; + vWrap = 33071 /* ClampToEdge */; + texture = null; + width = 0; + height = 0; + pma = false; + regions = new Array(); + constructor(name) { + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + for (let region of this.regions) + region.texture = texture; + } + }; + var TextureAtlasRegion = class extends TextureRegion { + page; + name; + x = 0; + y = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + index = 0; + degrees = 0; + names = null; + values = null; + constructor(page, name) { + super(); + this.page = page; + this.name = name; + page.regions.push(this); + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class _MeshAttachment extends VertexAttachment { + region = null; + /** The name of the texture region for this attachment. */ + path; + /** The UV pair for each vertex, normalized within the texture region. */ + regionUVs = []; + /** The UV pair for each vertex, normalized within the entire texture. + * + * See {@link #updateUVs}. */ + uvs = []; + /** Triplets of vertex indices which describe the mesh's triangulation. */ + triangles = []; + /** The color to tint the mesh. */ + color = new Color(1, 1, 1, 1); + /** The width of the mesh's image. Available only when nonessential data was exported. */ + width = 0; + /** The height of the mesh's image. Available only when nonessential data was exported. */ + height = 0; + /** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */ + hullLength = 0; + /** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if + * nonessential data was exported. Triangulation is not performed at runtime. */ + edges = []; + parentMesh = null; + sequence = null; + tempColor = new Color(0, 0, 0, 0); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or + * the {@link #regionUVs} are changed. */ + updateRegion() { + if (!this.region) throw new Error("Region not set."); + let regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length); + let uvs = this.uvs; + let n = this.uvs.length; + let u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof TextureAtlasRegion) { + let region = this.region, page = region.page; + let textureWidth = page.width, textureHeight = page.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } else if (!this.region) { + u = v = 0; + width = height = 1; + } else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices}, + * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the + * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */ + getParentMesh() { + return this.parentMesh; + } + /** @param parentMesh May be null. */ + setParentMesh(parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + } + copy() { + if (this.parentMesh) return this.newLinkedMesh(); + let copy = new _MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = this.uvs instanceof Float32Array ? Utils.newFloatArray(this.uvs.length) : new Array(this.uvs.length); + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + if (this.edges) { + copy.edges = new Array(this.edges.length); + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + if (this.sequence != null) this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices2, offset, stride); + } + /** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/ + newLinkedMesh() { + let copy = new _MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + copy.timelineAttachment = this.timelineAttachment; + copy.setParentMesh(this.parentMesh ? this.parentMesh : this); + if (copy.region != null) copy.updateRegion(); + return copy; + } + }; + + // spine-core/src/attachments/PathAttachment.ts + var PathAttachment = class _PathAttachment extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ + lengths = []; + /** If true, the start and end knots are connected. */ + closed = false; + /** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer + * calculations are performed but calculating positions along the path is less accurate. */ + constantSpeed = false; + /** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually + * rendered at runtime. */ + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new _PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PointAttachment.ts + var PointAttachment = class _PointAttachment extends VertexAttachment { + x = 0; + y = 0; + rotation = 0; + /** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments + * are not usually rendered at runtime. */ + color = new Color(0.38, 0.94, 0, 1); + constructor(name) { + super(name); + } + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + computeWorldRotation(bone) { + const r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const x = cos * bone.a + sin * bone.b; + const y = cos * bone.c + sin * bone.d; + return MathUtils.atan2Deg(y, x); + } + copy() { + let copy = new _PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/RegionAttachment.ts + var RegionAttachment = class _RegionAttachment extends Attachment { + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local rotation. */ + rotation = 0; + /** The width of the region attachment in Spine. */ + width = 0; + /** The height of the region attachment in Spine. */ + height = 0; + /** The color to tint the region attachment. */ + color = new Color(1, 1, 1, 1); + /** The name of the texture region for this attachment. */ + path; + region = null; + sequence = null; + /** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex. + * + * See {@link #updateOffset()}. */ + offset = Utils.newFloatArray(8); + uvs = Utils.newFloatArray(8); + tempColor = new Color(1, 1, 1, 1); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */ + updateRegion() { + if (!this.region) throw new Error("Region not set."); + let region = this.region; + let uvs = this.uvs; + if (region == null) { + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + uvs[4] = 1; + uvs[5] = 1; + uvs[6] = 1; + uvs[7] = 0; + return; + } + let regionScaleX = this.width / this.region.originalWidth * this.scaleX; + let regionScaleY = this.height / this.region.originalHeight * this.scaleY; + let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + let localX2 = localX + this.region.width * regionScaleX; + let localY2 = localY + this.region.height * regionScaleY; + let radians = this.rotation * MathUtils.degRad; + let cos = Math.cos(radians); + let sin = Math.sin(radians); + let x = this.x, y = this.y; + let localXCos = localX * cos + x; + let localXSin = localX * sin; + let localYCos = localY * cos + y; + let localYSin = localY * sin; + let localX2Cos = localX2 * cos + x; + let localX2Sin = localX2 * sin; + let localY2Cos = localY2 * cos + y; + let localY2Sin = localY2 * sin; + let offset = this.offset; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + if (region.degrees == 90) { + uvs[0] = region.u2; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + } else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + } + /** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may + * be changed. + *

+ * See World transforms in the Spine + * Runtimes Guide. + * @param worldVertices The output world vertices. Must have a length >= offset + 8. + * @param offset The worldVertices index to begin writing values. + * @param stride The number of worldVertices entries between the value pairs written. */ + computeWorldVertices(slot, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + let bone = slot.bone; + let vertexOffset = this.offset; + let x = bone.worldX, y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = 0, offsetY = 0; + offsetX = vertexOffset[0]; + offsetY = vertexOffset[1]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[2]; + offsetY = vertexOffset[3]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[4]; + offsetY = vertexOffset[5]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[6]; + offsetY = vertexOffset[7]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + } + copy() { + let copy = new _RegionAttachment(this.name, this.path); + copy.region = this.region; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + return copy; + } + static X1 = 0; + static Y1 = 1; + static C1R = 2; + static C1G = 3; + static C1B = 4; + static C1A = 5; + static U1 = 6; + static V1 = 7; + static X2 = 8; + static Y2 = 9; + static C2R = 10; + static C2G = 11; + static C2B = 12; + static C2A = 13; + static U2 = 14; + static V2 = 15; + static X3 = 16; + static Y3 = 17; + static C3R = 18; + static C3G = 19; + static C3B = 20; + static C3A = 21; + static U3 = 22; + static V3 = 23; + static X4 = 24; + static Y4 = 25; + static C4R = 26; + static C4G = 27; + static C4B = 28; + static C4A = 29; + static U4 = 30; + static V4 = 31; + }; + + // spine-core/src/AtlasAttachmentLoader.ts + var AtlasAttachmentLoader = class { + atlas; + constructor(atlas) { + this.atlas = atlas; + } + loadSequence(name, basePath, sequence) { + let regions = sequence.regions; + for (let i = 0, n = regions.length; i < n; i++) { + let path = sequence.getPath(basePath, i); + let region = this.atlas.findRegion(path); + if (region == null) throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")"); + regions[i] = region; + } + } + newRegionAttachment(skin, name, path, sequence) { + let attachment = new RegionAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newMeshAttachment(skin, name, path, sequence) { + let attachment = new MeshAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newBoundingBoxAttachment(skin, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, name) { + return new ClippingAttachment(name); + } + }; + + // spine-core/src/BoneData.ts + var BoneData = class { + /** The index of the bone in {@link Skeleton#getBones()}. */ + index = 0; + /** The name of the bone, which is unique across all bones in the skeleton. */ + name; + /** @returns May be null. */ + parent = null; + /** The bone's length. */ + length = 0; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local shearX. */ + shearX = 0; + /** The local shearX. */ + shearY = 0; + /** The transform mode for how parent world transforms affect this bone. */ + inherit = 0 /* Normal */; + /** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this + * bone. + * @see Skin#bones */ + skinRequired = false; + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually + * rendered at runtime. */ + color = new Color(); + /** The bone icon as it was in Spine, or null if nonessential data was not exported. */ + icon; + /** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = false; + constructor(index, name, parent) { + if (index < 0) throw new Error("index must be >= 0."); + if (!name) throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + }; + var Inherit = /* @__PURE__ */ ((Inherit2) => { + Inherit2[Inherit2["Normal"] = 0] = "Normal"; + Inherit2[Inherit2["OnlyTranslation"] = 1] = "OnlyTranslation"; + Inherit2[Inherit2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + Inherit2[Inherit2["NoScale"] = 3] = "NoScale"; + Inherit2[Inherit2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + return Inherit2; + })(Inherit || {}); + + // spine-core/src/Bone.ts + var Bone = class { + /** The bone's setup pose data. */ + data; + /** The skeleton this bone belongs to. */ + skeleton; + /** The parent bone, or null if this is the root bone. */ + parent = null; + /** The immediate children of this bone. */ + children = new Array(); + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 0; + /** The local scaleY. */ + scaleY = 0; + /** The local shearX. */ + shearX = 0; + /** The local shearY. */ + shearY = 0; + /** The applied local x translation. */ + ax = 0; + /** The applied local y translation. */ + ay = 0; + /** The applied local rotation in degrees, counter clockwise. */ + arotation = 0; + /** The applied local scaleX. */ + ascaleX = 0; + /** The applied local scaleY. */ + ascaleY = 0; + /** The applied local shearX. */ + ashearX = 0; + /** The applied local shearY. */ + ashearY = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + a = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + b = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + c = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + d = 0; + /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldY = 0; + /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldX = 0; + inherit = 0 /* Normal */; + sorted = false; + active = false; + /** @param parent May be null. */ + constructor(data, skeleton, parent) { + if (!data) throw new Error("data cannot be null."); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + /** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the + * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */ + isActive() { + return this.active; + } + /** Computes the world transform using the parent bone and this bone's local applied transform. */ + update(physics) { + this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY); + } + /** Computes the world transform using the parent bone and this bone's local transform. + * + * See {@link #updateWorldTransformWith()}. */ + updateWorldTransform() { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + } + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + let parent = this.parent; + if (!parent) { + let skeleton = this.skeleton; + const sx = skeleton.scaleX, sy = skeleton.scaleY; + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX * sx; + this.b = Math.cos(ry) * scaleY * sx; + this.c = Math.sin(rx) * scaleX * sy; + this.d = Math.sin(ry) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.inherit) { + case 0 /* Normal */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case 1 /* OnlyTranslation */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX; + this.b = Math.cos(ry) * scaleY; + this.c = Math.sin(rx) * scaleX; + this.d = Math.sin(ry) * scaleY; + break; + } + case 2 /* NoRotationOrReflection */: { + let sx = 1 / this.skeleton.scaleX, sy = 1 / this.skeleton.scaleY; + pa *= sx; + pc *= sy; + let s = pa * pa + pc * pc; + let prx = 0; + if (s > 1e-4) { + s = Math.abs(pa * pd * sy - pb * sx * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * MathUtils.radDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg; + } + const rx = (rotation + shearX - prx) * MathUtils.degRad; + const ry = (rotation + shearY - prx + 90) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + rotation *= MathUtils.degRad; + const cos = Math.cos(rotation), sin = Math.sin(rotation); + let za = (pa * cos + pb * sin) / this.skeleton.scaleX; + let zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(za * za + zc * zc); + if (s > 1e-5) s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.inherit == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s; + rotation = Math.PI / 2 + Math.atan2(zc, za); + const zb = Math.cos(rotation) * s; + const zd = Math.sin(rotation) * s; + shearX *= MathUtils.degRad; + shearY = (90 + shearY) * MathUtils.degRad; + const la = Math.cos(shearX) * scaleX; + const lb = Math.cos(shearY) * scaleY; + const lc = Math.sin(shearX) * scaleX; + const ld = Math.sin(shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + } + /** Sets this bone's local transform to the setup pose. */ + setToSetupPose() { + let data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + this.inherit = data.inherit; + } + /** Computes the applied transform values from the world transform. + * + * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, etc) then this method should be called so + * the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply other + * constraints). + * + * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after + * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ + updateAppliedTransform() { + let parent = this.parent; + if (!parent) { + this.ax = this.worldX - this.skeleton.x; + this.ay = this.worldY - this.skeleton.y; + this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + let pid = 1 / (pa * pd - pb * pc); + let ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = dx * ia - dy * ib; + this.ay = dy * id - dx * ic; + let ra, rb, rc, rd; + if (this.inherit == 1 /* OnlyTranslation */) { + ra = this.a; + rb = this.b; + rc = this.c; + rd = this.d; + } else { + switch (this.inherit) { + case 2 /* NoRotationOrReflection */: { + let s2 = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + pb = -pc * this.skeleton.scaleX * s2 / this.skeleton.scaleY; + pd = pa * this.skeleton.scaleY * s2 / this.skeleton.scaleX; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation); + pa = (pa * cos + pb * sin) / this.skeleton.scaleX; + pc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(pa * pa + pc * pc); + if (s > 1e-5) s = 1 / s; + pa *= s; + pc *= s; + s = Math.sqrt(pa * pa + pc * pc); + if (this.inherit == 3 /* NoScale */ && pid < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s; + let r = MathUtils.PI / 2 + Math.atan2(pc, pa); + pb = Math.cos(r) * s; + pd = Math.sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + } + ra = ia * this.a - ib * this.c; + rb = ia * this.b - ib * this.d; + rc = id * this.c - ic * this.a; + rd = id * this.d - ic * this.b; + } + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 1e-4) { + let det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg; + } else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg; + } + } + /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ + getWorldRotationX() { + return Math.atan2(this.c, this.a) * MathUtils.radDeg; + } + /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ + getWorldRotationY() { + return Math.atan2(this.d, this.b) * MathUtils.radDeg; + } + /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + /** Transforms a point from world coordinates to the bone's local coordinates. */ + worldToLocal(world) { + let invDet = 1 / (this.a * this.d - this.b * this.c); + let x = world.x - this.worldX, y = world.y - this.worldY; + world.x = x * this.d * invDet - y * this.b * invDet; + world.y = y * this.a * invDet - x * this.c * invDet; + return world; + } + /** Transforms a point from the bone's local coordinates to world coordinates. */ + localToWorld(local) { + let x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + worldToParent(world) { + if (world == null) throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.worldToLocal(world); + } + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + parentToWorld(world) { + if (world == null) throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.localToWorld(world); + } + /** Transforms a world rotation to a local rotation. */ + worldToLocalRotation(worldRotation) { + let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX; + } + /** Transforms a local rotation to a world rotation. */ + localToWorldRotation(localRotation) { + localRotation -= this.rotation - this.shearX; + let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + /** Rotates the world transform the specified amount. + *

+ * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and + * {@link #update(Physics)} will need to be called on any child bones, recursively. */ + rotateWorld(degrees) { + degrees *= MathUtils.degRad; + const sin = Math.sin(degrees), cos = Math.cos(degrees); + const ra = this.a, rb = this.b; + this.a = cos * ra - sin * this.c; + this.b = cos * rb - sin * this.d; + this.c = sin * ra + cos * this.c; + this.d = sin * rb + cos * this.d; + } + }; + + // spine-core/src/ConstraintData.ts + var ConstraintData = class { + constructor(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } + }; + + // spine-core/src/AssetManagerBase.ts + var AssetManagerBase = class { + pathPrefix = ""; + textureLoader; + downloader; + cache; + errors = {}; + toLoad = 0; + loaded = 0; + constructor(textureLoader, pathPrefix = "", downloader = new Downloader(), cache = new AssetCache()) { + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader; + this.cache = cache; + } + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.cache.assets[path] = asset; + this.cache.assetsRefCount[path] = (this.cache.assetsRefCount[path] || 0) + 1; + if (callback) callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) callback(path, message); + } + loadAll() { + let promise = new Promise((resolve, reject) => { + let check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) reject(this.errors); + else resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + resolve(data); + }, (status, responseText) => { + const errorMsg = `Couldn't load binary ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + loadText(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + resolve(data); + }, (status, responseText) => { + const errorMsg = `Couldn't load JSON ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + reuseAssets(path, success = () => { + }, error = () => { + }) { + const loadedStatus = this.cache.assetsLoaded[path]; + const alreadyExistsOrLoading = loadedStatus !== void 0; + if (alreadyExistsOrLoading) { + this.cache.assetsLoaded[path] = loadedStatus.then((data) => { + data = data instanceof Image || data instanceof ImageBitmap ? this.textureLoader(data) : data; + this.success(success, path, data); + return data; + }).catch((errorMsg) => this.error(error, path, errorMsg)); + } + return alreadyExistsOrLoading; + } + loadTexture(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + let isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) return response.blob(); + const errorMsg = `Couldn't load image: ${path}`; + this.error(error, path, `Couldn't load image: ${path}`); + reject(errorMsg); + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) { + const texture = this.createTexture(path, bitmap); + this.success(success, path, texture); + resolve(texture); + } + ; + }); + } else { + let image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + const texture = this.createTexture(path, image); + this.success(success, path, texture); + resolve(texture); + }; + image.onerror = () => { + const errorMsg = `Couldn't load image: ${path}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }; + if (this.downloader.rawDataUris[path]) path = this.downloader.rawDataUris[path]; + image.src = path; + } + }); + } + loadTextureAtlas(path, success = () => { + }, error = () => { + }, fileAlias) { + let index = path.lastIndexOf("/"); + let parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadText(path, (atlasText) => { + try { + const atlas = this.createTextureAtlas(path, atlasText); + let toLoad = atlas.pages.length, abort = false; + if (toLoad === 0) { + this.success(success, path, atlas); + resolve(atlas); + return; + } + for (let page of atlas.pages) { + this.loadTexture( + !fileAlias ? parent + page.name : fileAlias[page.name], + (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad == 0) { + this.success(success, path, atlas); + resolve(atlas); + } + } + }, + (imagePath, message) => { + if (!abort) { + const errorMsg = `Couldn't load texture ${path} page image: ${imagePath}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + abort = true; + } + ); + } + } catch (e) { + const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + }, (status, responseText) => { + const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + loadTextureAtlasButNoTextures(path, success = () => { + }, error = () => { + }, fileAlias) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadText(path, (atlasText) => { + try { + const atlas = this.createTextureAtlas(path, atlasText); + this.success(success, path, atlas); + resolve(atlas); + } catch (e) { + const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + }, (status, responseText) => { + const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + // Promisified versions of load function + async loadBinaryAsync(path) { + return new Promise((resolve, reject) => { + this.loadBinary( + path, + (_, binary) => resolve(binary), + (_, message) => reject(message) + ); + }); + } + async loadJsonAsync(path) { + return new Promise((resolve, reject) => { + this.loadJson( + path, + (_, object) => resolve(object), + (_, message) => reject(message) + ); + }); + } + async loadTextureAsync(path) { + return new Promise((resolve, reject) => { + this.loadTexture( + path, + (_, texture) => resolve(texture), + (_, message) => reject(message) + ); + }); + } + async loadTextureAtlasAsync(path) { + return new Promise((resolve, reject) => { + this.loadTextureAtlas( + path, + (_, atlas) => resolve(atlas), + (_, message) => reject(message) + ); + }); + } + async loadTextureAtlasButNoTexturesAsync(path) { + return new Promise((resolve, reject) => { + this.loadTextureAtlasButNoTextures( + path, + (_, atlas) => resolve(atlas), + (_, message) => reject(message) + ); + }); + } + setCache(cache) { + this.cache = cache; + } + get(path) { + return this.cache.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + let asset = this.cache.assets[path]; + if (asset) return asset; + let error = this.errors[path]; + throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + } + remove(path) { + path = this.pathPrefix + path; + let asset = this.cache.assets[path]; + if (asset.dispose) asset.dispose(); + delete this.cache.assets[path]; + delete this.cache.assetsRefCount[path]; + delete this.cache.assetsLoaded[path]; + return asset; + } + removeAll() { + for (let path in this.cache.assets) { + let asset = this.cache.assets[path]; + if (asset.dispose) asset.dispose(); + } + this.cache.assets = {}; + this.cache.assetsLoaded = {}; + this.cache.assetsRefCount = {}; + } + isLoadingComplete() { + return this.toLoad == 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + // dispose asset only if it's not used by others + disposeAsset(path) { + const asset = this.cache.assets[path]; + if (asset instanceof TextureAtlas) { + asset.dispose(); + return; + } + this.disposeAssetInternal(path); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } + disposeAssetInternal(path) { + if (this.cache.assetsRefCount[path] > 0 && --this.cache.assetsRefCount[path] === 0) { + return this.remove(path); + } + } + createTextureAtlas(path, atlasText) { + const atlas = new TextureAtlas(atlasText); + atlas.dispose = () => { + if (this.cache.assetsRefCount[path] <= 0) return; + this.disposeAssetInternal(path); + for (const page of atlas.pages) { + page.texture?.dispose(); + } + }; + return atlas; + } + createTexture(path, image) { + const texture = this.textureLoader(image); + const textureDispose = texture.dispose.bind(texture); + texture.dispose = () => { + if (this.disposeAssetInternal(path)) textureDispose(); + }; + return texture; + } + }; + var AssetCache = class _AssetCache { + assets = {}; + assetsRefCount = {}; + assetsLoaded = {}; + static AVAILABLE_CACHES = /* @__PURE__ */ new Map(); + static getCache(id) { + const cache = _AssetCache.AVAILABLE_CACHES.get(id); + if (cache) return cache; + const newCache = new _AssetCache(); + _AssetCache.AVAILABLE_CACHES.set(id, newCache); + return newCache; + } + async addAsset(path, asset) { + this.assetsLoaded[path] = Promise.resolve(asset); + this.assets[path] = await asset; + } + }; + var Downloader = class { + callbacks = {}; + rawDataUris = {}; + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx != -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx == -1) throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) return; + const rawDataUri = this.rawDataUris[url]; + if (rawDataUri && !rawDataUri.includes(".")) { + try { + this.finish(url, 200, this.dataUriToString(rawDataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", rawDataUri ? rawDataUri : url, true); + let done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) return; + const rawDataUri = this.rawDataUris[url]; + if (rawDataUri && !rawDataUri.includes(".")) { + try { + this.finish(url, 200, this.dataUriToUint8Array(rawDataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.open("GET", rawDataUri ? rawDataUri : url, true); + request.responseType = "arraybuffer"; + let onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status == 200 || request.status == 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + let callbacks = this.callbacks[url]; + delete this.callbacks[url]; + let args = status == 200 || status == 0 ? [data] : [status, data]; + for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) + callbacks[i].apply(null, args); + } + }; + + // spine-core/src/Event.ts + var Event = class { + data; + intValue = 0; + floatValue = 0; + stringValue = null; + time = 0; + volume = 0; + balance = 0; + constructor(time, data) { + if (!data) throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + }; + + // spine-core/src/EventData.ts + var EventData = class { + name; + intValue = 0; + floatValue = 0; + stringValue = null; + audioPath = null; + volume = 0; + balance = 0; + constructor(name) { + this.name = name; + } + }; + + // spine-core/src/IkConstraint.ts + var IkConstraint = class { + /** The IK constraint's setup pose data. */ + data; + /** The bones that will be modified by this IK constraint. */ + bones; + /** The bone that is the IK target. */ + target; + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 1; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + active = false; + constructor(data, skeleton) { + if (!data) throw new Error("data cannot be null."); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) throw new Error(`Couldn't find bone ${data.target.name}`); + this.target = target; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + update(physics) { + if (this.mix == 0) return; + let target = this.target; + let bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix); + break; + } + } + /** Applies 1 bone IK. The target is specified in the world coordinate system. */ + apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) { + let p = bone.parent; + if (!p) throw new Error("IK bone must have parent."); + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.inherit) { + case 1 /* OnlyTranslation */: + tx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX); + ty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY); + break; + case 2 /* NoRotationOrReflection */: + let s = Math.abs(pa * pd - pb * pc) / Math.max(1e-4, pa * pa + pc * pc); + let sa = pa / bone.skeleton.scaleX; + let sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg; + // Fall through + default: + let x = targetX - p.worldX, y = targetY - p.worldY; + let d = pa * pd - pb * pc; + if (Math.abs(d) <= 1e-4) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + } + rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg; + if (bone.ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + let sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.inherit) { + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + const b = bone.data.length * sx; + if (b > 1e-4) { + const dd = tx * tx + ty * ty; + if (compress && dd < b * b || stretch && dd > b * b) { + const s = (Math.sqrt(dd) / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } + } + bone.updateWorldTransformWith( + bone.ax, + bone.ay, + bone.arotation + rotationIK * alpha, + sx, + sy, + bone.ashearX, + bone.ashearY + ); + } + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ + apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) { + if (parent.inherit != 0 /* Normal */ || child.inherit != 0 /* Normal */) return; + let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + let u = Math.abs(psx - psy) <= 1e-4; + if (!u || stretch) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + let pp = parent.parent; + if (!pp) throw new Error("IK parent must itself have a parent."); + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; + id = Math.abs(id) <= 1e-4 ? 0 : 1 / id; + let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 1e-4) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5; + let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + let c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = Math.sqrt(r0) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + let os = Math.atan2(cy, cx) * s2; + let rotation = parent.arotation; + a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + } + }; + + // spine-core/src/IkConstraintData.ts + var IkConstraintData = class extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ + bones = new Array(); + /** The bone that is the IK target. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) throw new Error("BoneData not set."); + else return this._target; + } + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone + * is scaled on both the X and Y axes. */ + uniform = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 0; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/PathConstraintData.ts + var PathConstraintData = class extends ConstraintData { + /** The bones that will be modified by this path constraint. */ + bones = new Array(); + /** The slot whose path attachment will be used to constrained the bones. */ + _target = null; + set target(slotData) { + this._target = slotData; + } + get target() { + if (!this._target) throw new Error("SlotData not set."); + else return this._target; + } + /** The mode for positioning the first bone on the path. */ + positionMode = 0 /* Fixed */; + /** The mode for positioning the bones after the first bone on the path. */ + spacingMode = 1 /* Fixed */; + /** The mode for adjusting the rotation of the bones. */ + rotateMode = 1 /* Chain */; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + constructor(name) { + super(name, 0, false); + } + }; + var PositionMode = /* @__PURE__ */ ((PositionMode2) => { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + return PositionMode2; + })(PositionMode || {}); + var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + return SpacingMode2; + })(SpacingMode || {}); + var RotateMode = /* @__PURE__ */ ((RotateMode2) => { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + return RotateMode2; + })(RotateMode || {}); + + // spine-core/src/PathConstraint.ts + var PathConstraint = class _PathConstraint { + static NONE = -1; + static BEFORE = -2; + static AFTER = -3; + static epsilon = 1e-5; + /** The path constraint's setup pose data. */ + data; + /** The bones that will be modified by this path constraint. */ + bones; + /** The slot whose path attachment will be used to constrained the bones. */ + target; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + spaces = new Array(); + positions = new Array(); + world = new Array(); + curves = new Array(); + lengths = new Array(); + segments = new Array(); + active = false; + constructor(data, skeleton) { + if (!data) throw new Error("data cannot be null."); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0, n = data.bones.length; i < n; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findSlot(data.target.name); + if (!target) throw new Error(`Couldn't find target bone ${data.target.name}`); + this.target = target; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + update(physics) { + let attachment = this.target.getAttachment(); + if (!(attachment instanceof PathAttachment)) return; + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; + let data = this.data; + let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */; + let bones = this.bones; + let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + let spacing = this.spacing; + switch (data.spacingMode) { + case 2 /* Percent */: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + let bone = bones[i]; + let setupLength = bone.data.length; + let x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case 3 /* Proportional */: + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + let lengthSpacing = data.spacingMode == 0 /* Length */; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + let positions = this.computeWorldPositions(attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation == 0) + tip = data.rotateMode == 1 /* Chain */; + else { + tip = false; + let p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, p = 3; i < boneCount; i++, p += 3) { + let bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + let length = lengths[i]; + if (length != 0) { + let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + let length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.updateAppliedTransform(); + } + } + computeWorldPositions(path, spacesCount, tangents) { + let target = this.target; + let position = this.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world; + let closed2 = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + let lengths = path.lengths; + curveCount -= closed2 ? 1 : 2; + let pathLength2 = lengths[curveCount]; + if (this.data.positionMode == 1 /* Percent */) position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier2 = pathLength2; + break; + case 3 /* Proportional */: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed2) { + p %= pathLength2; + if (p < 0) p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve != _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve != _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + let length = lengths[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + let prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed2 && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition( + p, + world[0], + world[1], + world[2], + world[3], + world[4], + world[5], + world[6], + world[7], + out, + o, + tangents || i > 0 && space == 0 + ); + } + return out; + } + if (closed2) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + let curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode == 1 /* Percent */) position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier = pathLength; + break; + case 3 /* Proportional */: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + let segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed2) { + p %= pathLength; + if (p < 0) p += pathLength; + curve = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + let length = curves[curve]; + if (p > length) continue; + if (curve == 0) + p /= length; + else { + let prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + let length = segments[segment]; + if (p > length) continue; + if (segment == 0) + p /= length; + else { + let prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } + }; + + // spine-core/src/PhysicsConstraint.ts + var PhysicsConstraint = class { + data; + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(bone) { + this._bone = bone; + } + get bone() { + if (!this._bone) throw new Error("Bone not set."); + else return this._bone; + } + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + mix = 0; + _reset = true; + ux = 0; + uy = 0; + cx = 0; + cy = 0; + tx = 0; + ty = 0; + xOffset = 0; + xVelocity = 0; + yOffset = 0; + yVelocity = 0; + rotateOffset = 0; + rotateVelocity = 0; + scaleOffset = 0; + scaleVelocity = 0; + active = false; + skeleton; + remaining = 0; + lastTime = 0; + constructor(data, skeleton) { + this.data = data; + this.skeleton = skeleton; + this.bone = skeleton.bones[data.bone.index]; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + reset() { + this.remaining = 0; + this.lastTime = this.skeleton.time; + this._reset = true; + this.xOffset = 0; + this.xVelocity = 0; + this.yOffset = 0; + this.yVelocity = 0; + this.rotateOffset = 0; + this.rotateVelocity = 0; + this.scaleOffset = 0; + this.scaleVelocity = 0; + } + setToSetupPose() { + const data = this.data; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + isActive() { + return this.active; + } + /** Applies the constraint to the constrained bones. */ + update(physics) { + const mix = this.mix; + if (mix == 0) return; + const x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0; + const bone = this.bone; + const l = bone.data.length; + switch (physics) { + case 0 /* none */: + return; + case 1 /* reset */: + this.reset(); + // Fall through. + case 2 /* update */: + const skeleton = this.skeleton; + const delta = Math.max(this.skeleton.time - this.lastTime, 0); + this.remaining += delta; + this.lastTime = skeleton.time; + const bx = bone.worldX, by = bone.worldY; + if (this._reset) { + this._reset = false; + this.ux = bx; + this.uy = by; + } else { + let a = this.remaining, i = this.inertia, t = this.data.step, f = this.skeleton.data.referenceScale, d = -1; + let qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY); + qx *= Math.abs(skeleton.scaleX); + if (x || y) { + if (x) { + const u = (this.ux - bx) * i; + this.xOffset += u > qx ? qx : u < -qx ? -qx : u; + this.ux = bx; + } + if (y) { + const u = (this.uy - by) * i; + this.yOffset += u > qy ? qy : u < -qy ? -qy : u; + this.uy = by; + } + if (a >= t) { + d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind * f * skeleton.scaleX, g = this.gravity * f * skeleton.scaleY; + do { + if (x) { + this.xVelocity += (w - this.xOffset * e) * m; + this.xOffset += this.xVelocity * t; + this.xVelocity *= d; + } + if (y) { + this.yVelocity -= (g + this.yOffset * e) * m; + this.yOffset += this.yVelocity * t; + this.yVelocity *= d; + } + a -= t; + } while (a >= t); + } + if (x) bone.worldX += this.xOffset * mix * this.data.x; + if (y) bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX || scaleX) { + let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0; + let dx = this.cx - bone.worldX, dy = this.cy - bone.worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx) + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy) + dy = -qy; + if (rotateOrShearX) { + mr = (this.data.rotate + this.data.shearX) * mix; + let r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr; + this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; + r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + if (scaleX) { + r = l * bone.getWorldScaleX(); + if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = Math.cos(ca); + s = Math.sin(ca); + const r = l * bone.getWorldScaleX(); + if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + } + a = this.remaining; + if (a >= t) { + if (d == -1) d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind, g = Skeleton.yDown ? -this.gravity : this.gravity, h = l / f; + while (true) { + a -= t; + if (scaleX) { + this.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m; + this.scaleOffset += this.scaleVelocity * t; + this.scaleVelocity *= d; + } + if (rotateOrShearX) { + this.rotateVelocity -= ((w * s + g * c) * h + this.rotateOffset * e) * m; + this.rotateOffset += this.rotateVelocity * t; + this.rotateVelocity *= d; + if (a < t) break; + const r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + } else if (a < t) + break; + } + } + } + this.remaining = a; + } + this.cx = bone.worldX; + this.cy = bone.worldY; + break; + case 3 /* pose */: + if (x) bone.worldX += this.xOffset * mix * this.data.x; + if (y) bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX) { + let o = this.rotateOffset * mix, s = 0, c = 0, a = 0; + if (this.data.shearX > 0) { + let r = 0; + if (this.data.rotate > 0) { + r = o * this.data.rotate; + s = Math.sin(r); + c = Math.cos(r); + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + r += o * this.data.shearX; + s = Math.sin(r); + c = Math.cos(r); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + } else { + o *= this.data.rotate; + s = Math.sin(o); + c = Math.cos(o); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + } + if (scaleX) { + const s = 1 + this.scaleOffset * mix * this.data.scaleX; + bone.a *= s; + bone.c *= s; + } + if (physics != 3 /* pose */) { + this.tx = l * bone.a; + this.ty = l * bone.c; + } + bone.updateAppliedTransform(); + } + /** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional + * amount in world space. */ + translate(x, y) { + this.ux -= x; + this.uy -= y; + this.cx -= x; + this.cy -= y; + } + /** Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the + * specified point in world space. */ + rotate(x, y, degrees) { + const r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const dx = this.cx - x, dy = this.cy - y; + this.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); + } + }; + + // spine-core/src/Slot.ts + var Slot = class { + /** The slot's setup pose data. */ + data; + /** The bone this slot belongs to. */ + bone; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color; + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + attachment = null; + attachmentState = 0; + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence#getSetupIndex()}. */ + sequenceIndex = -1; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * + * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */ + deform = new Array(); + constructor(data, bone) { + if (!data) throw new Error("data cannot be null."); + if (!bone) throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new Color(); + this.darkColor = !data.darkColor ? null : new Color(); + this.setToSetupPose(); + } + /** The skeleton this slot belongs to. */ + getSkeleton() { + return this.bone.skeleton; + } + /** The current attachment for the slot, or null if the slot has no attachment. */ + getAttachment() { + return this.attachment; + } + /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the + * specified attachment. */ + setAttachment(attachment) { + if (this.attachment == attachment) return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + /** Sets this slot to the setup pose. */ + setToSetupPose() { + this.color.setFromColor(this.data.color); + if (this.darkColor) this.darkColor.setFromColor(this.data.darkColor); + if (!this.data.attachmentName) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } + }; + + // spine-core/src/TransformConstraint.ts + var TransformConstraint = class { + /** The transform constraint's setup pose data. */ + data; + /** The bones that will be modified by this transform constraint. */ + bones; + /** The target bone whose world transform will be copied to the constrained bones. */ + target; + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + temp = new Vector2(); + active = false; + constructor(data, skeleton) { + if (!data) throw new Error("data cannot be null."); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) throw new Error(`Couldn't find target bone ${data.target.name}.`); + this.target = target; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + update(physics) { + if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) return; + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + } + applyAbsoluteWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect; + let offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * mixX; + bone.worldY += (temp.y - bone.worldY) * mixY; + } + if (mixScaleX != 0) { + let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + if (s != 0) s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + if (s != 0) s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let b = bone.b, d = bone.d; + let by = Math.atan2(d, b); + let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r = by + (r + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyRelativeWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * mixX; + bone.worldY += temp.y * mixY; + } + if (mixScaleX != 0) { + let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + let b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyAbsoluteLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation; + if (mixRotate != 0) rotation += (target.arotation - rotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax, y = bone.ay; + x += (target.ax - x + this.data.offsetX) * mixX; + y += (target.ay - y + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY; + let shearY = bone.ashearY; + if (mixShearY != 0) shearY += (target.ashearY - shearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + applyRelativeLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax + (target.ax + this.data.offsetX) * mixX; + let y = bone.ay + (target.ay + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1); + let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1); + let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + }; + + // spine-core/src/Skeleton.ts + var Skeleton = class _Skeleton { + static quadTriangles = [0, 1, 2, 2, 3, 0]; + static yDown = false; + /** The skeleton's setup pose data. */ + data; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones; + /** The skeleton's slots in the setup pose draw order. */ + slots; + /** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */ + drawOrder; + /** The skeleton's IK constraints. */ + ikConstraints; + /** The skeleton's transform constraints. */ + transformConstraints; + /** The skeleton's path constraints. */ + pathConstraints; + /** The skeleton's physics constraints. */ + physicsConstraints; + /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */ + _updateCache = new Array(); + /** The skeleton's current skin. May be null. */ + skin = null; + /** The color to tint all the skeleton's attachments. */ + color; + /** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + scaleX = 1; + /** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + _scaleY = 1; + get scaleY() { + return _Skeleton.yDown ? -this._scaleY : this._scaleY; + } + set scaleY(scaleY) { + this._scaleY = scaleY; + } + /** Sets the skeleton X position, which is added to the root bone worldX position. */ + x = 0; + /** Sets the skeleton Y position, which is added to the root bone worldY position. */ + y = 0; + /** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}. + *

+ * See {@link #update(float)}. */ + time = 0; + constructor(data) { + if (!data) throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, this, null); + else { + let parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (let i = 0; i < data.slots.length; i++) { + let slotData = data.slots[i]; + let bone = this.bones[slotData.boneData.index]; + let slot = new Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (let i = 0; i < data.ikConstraints.length; i++) { + let ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (let i = 0; i < data.transformConstraints.length; i++) { + let transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (let i = 0; i < data.pathConstraints.length; i++) { + let pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new PathConstraint(pathConstraintData, this)); + } + this.physicsConstraints = new Array(); + for (let i = 0; i < data.physicsConstraints.length; i++) { + let physicsConstraintData = data.physicsConstraints[i]; + this.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this)); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones, + * constraints, or weighted path attachments are added or removed. */ + updateCache() { + let updateCache = this._updateCache; + updateCache.length = 0; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin) { + let skinBones = this.skin.bones; + for (let i = 0, n = this.skin.bones.length; i < n; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + let ikConstraints = this.ikConstraints; + let transformConstraints = this.transformConstraints; + let pathConstraints = this.pathConstraints; + let physicsConstraints = this.physicsConstraints; + let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length; + let constraintCount = ikCount + transformCount + pathCount + physicsCount; + outer: + for (let i = 0; i < constraintCount; i++) { + for (let ii = 0; ii < ikCount; ii++) { + let constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < transformCount; ii++) { + let constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < pathCount; ii++) { + let constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < physicsCount; ii++) { + const constraint = physicsConstraints[ii]; + if (constraint.data.order == i) { + this.sortPhysicsConstraint(constraint); + continue outer; + } + } + } + for (let i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + } + sortIkConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) return; + let target = constraint.target; + this.sortBone(target); + let constrained = constraint.bones; + let parent = constrained[0]; + this.sortBone(parent); + if (constrained.length == 1) { + this._updateCache.push(constraint); + this.sortReset(parent.children); + } else { + let child = constrained[constrained.length - 1]; + this.sortBone(child); + this._updateCache.push(constraint); + this.sortReset(parent.children); + child.sorted = true; + } + } + sortPathConstraint(constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) return; + let slot = constraint.target; + let slotIndex = slot.data.index; + let slotBone = slot.bone; + if (this.skin) this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (let i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + let attachment = slot.getAttachment(); + if (attachment instanceof PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone); + let constrained = constraint.bones; + let boneCount = constrained.length; + for (let i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortTransformConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) return; + this.sortBone(constraint.target); + let constrained = constraint.bones; + let boneCount = constrained.length; + if (constraint.data.local) { + for (let i = 0; i < boneCount; i++) { + let child = constrained[i]; + this.sortBone(child.parent); + this.sortBone(child); + } + } else { + for (let i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortPathConstraintAttachment(skin, slotIndex, slotBone) { + let attachments = skin.attachments[slotIndex]; + if (!attachments) return; + for (let key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + } + sortPathConstraintAttachmentWith(attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) return; + let pathBones = attachment.bones; + if (!pathBones) + this.sortBone(slotBone); + else { + let bones = this.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + this.sortBone(bones[pathBones[i++]]); + } + } + } + sortPhysicsConstraint(constraint) { + const bone = constraint.bone; + constraint.active = bone.active && (!constraint.data.skinRequired || this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) return; + this.sortBone(bone); + this._updateCache.push(constraint); + this.sortReset(bone.children); + bone.sorted = true; + } + sortBone(bone) { + if (!bone) return; + if (bone.sorted) return; + let parent = bone.parent; + if (parent) this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (!bone.active) continue; + if (bone.sorted) this.sortReset(bone.children); + bone.sorted = false; + } + } + /** Updates the world transform for each bone and applies all constraints. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransform(physics) { + if (physics === void 0 || physics === null) throw new Error("physics is undefined"); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(physics); + } + updateWorldTransformWith(physics, parent) { + if (!parent) throw new Error("parent cannot be null."); + let bones = this.bones; + for (let i = 1, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let rootBone = this.getRootBone(); + if (!rootBone) throw new Error("Root bone must not be null."); + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + rootBone.worldX = pa * this.x + pb * this.y + parent.worldX; + rootBone.worldY = pc * this.x + pd * this.y + parent.worldY; + const rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad; + const ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad; + const la = Math.cos(rx) * rootBone.scaleX; + const lb = Math.cos(ry) * rootBone.scaleY; + const lc = Math.sin(rx) * rootBone.scaleX; + const ld = Math.sin(ry) * rootBone.scaleY; + rootBone.a = (pa * la + pb * lc) * this.scaleX; + rootBone.b = (pa * lb + pb * ld) * this.scaleX; + rootBone.c = (pc * la + pd * lc) * this.scaleY; + rootBone.d = (pc * lb + pd * ld) * this.scaleY; + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) { + let updatable = updateCache[i]; + if (updatable != rootBone) updatable.update(physics); + } + } + /** Sets the bones, constraints, and slots to their setup pose values. */ + setToSetupPose() { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + } + /** Sets the bones and constraints to their setup pose values. */ + setBonesToSetupPose() { + for (const bone of this.bones) bone.setToSetupPose(); + for (const constraint of this.ikConstraints) constraint.setToSetupPose(); + for (const constraint of this.transformConstraints) constraint.setToSetupPose(); + for (const constraint of this.pathConstraints) constraint.setToSetupPose(); + for (const constraint of this.physicsConstraints) constraint.setToSetupPose(); + } + /** Sets the slots and draw order to their setup pose values. */ + setSlotsToSetupPose() { + let slots = this.slots; + Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + } + /** @returns May return null. */ + getRootBone() { + if (this.bones.length == 0) return null; + return this.bones[0]; + } + /** @returns May be null. */ + findBone(boneName) { + if (!boneName) throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.data.name == boneName) return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) return slot; + } + return null; + } + /** Sets a skin by name. + * + * See {@link #setSkin()}. */ + setSkinByName(skinName) { + let skin = this.data.findSkin(skinName); + if (!skin) throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + } + /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the + * skin is changed, {@link #updateCache()} is called. + * + * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no + * old skin, each slot's setup mode attachment is attached from the new skin. + * + * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the + * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + * @param newSkin May be null. */ + setSkin(newSkin) { + if (newSkin == this.skin) return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let name = slot.data.attachmentName; + if (name) { + let attachment = newSkin.getAttachment(i, name); + if (attachment) slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment + * name. + * + * See {@link #getAttachment()}. + * @returns May be null. */ + getAttachmentByName(slotName, attachmentName) { + let slot = this.data.findSlot(slotName); + if (!slot) throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.index, attachmentName); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. + * @returns May be null. */ + getAttachment(slotIndex, attachmentName) { + if (!attachmentName) throw new Error("attachmentName cannot be null."); + if (this.skin) { + let attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) return attachment; + } + if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + } + /** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with + * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}. + * @param attachmentName May be null to clear the slot's attachment. */ + setAttachment(slotName, attachmentName) { + if (!slotName) throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) { + let attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (!attachment) throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + return this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it repeatedly. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + return this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + return this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this + * method than to call it repeatedly. */ + findPhysicsConstraint(constraintName) { + if (constraintName == null) throw new Error("constraintName cannot be null."); + return this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`. + * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */ + getBoundsRect(clipper) { + let offset = new Vector2(); + let size = new Vector2(); + this.getBounds(offset, size, void 0, clipper); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. + * @param clipper {@link SkeletonClipping} to use. If null, no clipping is applied. */ + getBounds(offset, size, temp = new Array(2), clipper = null) { + if (!offset) throw new Error("offset cannot be null."); + if (!size) throw new Error("size cannot be null."); + let drawOrder = this.drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + if (!slot.bone.active) continue; + let verticesLength = 0; + let vertices = null; + let triangles = null; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot, vertices, 0, 2); + triangles = _Skeleton.quadTriangles; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + triangles = mesh.triangles; + } else if (attachment instanceof ClippingAttachment && clipper != null) { + clipper.clipStart(slot, attachment); + continue; + } + if (vertices && triangles) { + if (clipper != null && clipper.isClipping()) { + clipper.clipTriangles(vertices, triangles, triangles.length); + vertices = clipper.clippedVertices; + verticesLength = clipper.clippedVertices.length; + } + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + if (clipper != null) clipper.clipEndWithSlot(slot); + } + if (clipper != null) clipper.clipEnd(); + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + /** Increments the skeleton's {@link #time}. */ + update(delta) { + this.time += delta; + } + physicsTranslate(x, y) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].translate(x, y); + } + /** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */ + physicsRotate(x, y, degrees) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].rotate(x, y, degrees); + } + }; + var Physics = /* @__PURE__ */ ((Physics2) => { + Physics2[Physics2["none"] = 0] = "none"; + Physics2[Physics2["reset"] = 1] = "reset"; + Physics2[Physics2["update"] = 2] = "update"; + Physics2[Physics2["pose"] = 3] = "pose"; + return Physics2; + })(Physics || {}); + + // spine-core/src/PhysicsConstraintData.ts + var PhysicsConstraintData = class extends ConstraintData { + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(boneData) { + this._bone = boneData; + } + get bone() { + if (!this._bone) throw new Error("BoneData not set."); + else return this._bone; + } + x = 0; + y = 0; + rotate = 0; + scaleX = 0; + shearX = 0; + limit = 0; + step = 0; + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ + mix = 0; + inertiaGlobal = false; + strengthGlobal = false; + dampingGlobal = false; + massGlobal = false; + windGlobal = false; + gravityGlobal = false; + mixGlobal = false; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/SkeletonData.ts + var SkeletonData = class { + /** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */ + name = null; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones = new Array(); + // Ordered parents first. + /** The skeleton's slots in the setup pose draw order. */ + slots = new Array(); + // Setup pose draw order. + skins = new Array(); + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See {@link Skeleton#getAttachmentByName()}. + * May be null. */ + defaultSkin = null; + /** The skeleton's events. */ + events = new Array(); + /** The skeleton's animations. */ + animations = new Array(); + /** The skeleton's IK constraints. */ + ikConstraints = new Array(); + /** The skeleton's transform constraints. */ + transformConstraints = new Array(); + /** The skeleton's path constraints. */ + pathConstraints = new Array(); + /** The skeleton's physics constraints. */ + physicsConstraints = new Array(); + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + x = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + y = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ + width = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ + height = 0; + /** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default + * is 100. */ + referenceScale = 100; + /** The Spine version used to export the skeleton data, or null. */ + version = null; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */ + hash = null; + // Nonessential + /** The dopesheet FPS in Spine. Available only when nonessential data was exported. */ + fps = 0; + /** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + imagesPath = null; + /** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + audioPath = null; + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findBone(boneName) { + if (!boneName) throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.name == boneName) return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.name == slotName) return slot; + } + return null; + } + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSkin(skinName) { + if (!skinName) throw new Error("skinName cannot be null."); + let skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) { + let skin = skins[i]; + if (skin.name == skinName) return skin; + } + return null; + } + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findEvent(eventDataName) { + if (!eventDataName) throw new Error("eventDataName cannot be null."); + let events = this.events; + for (let i = 0, n = events.length; i < n; i++) { + let event = events[i]; + if (event.name == eventDataName) return event; + } + return null; + } + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @returns May be null. */ + findAnimation(animationName) { + if (!animationName) throw new Error("animationName cannot be null."); + let animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) { + let animation = animations[i]; + if (animation.name == animationName) return animation; + } + return null; + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + const ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + const constraint = ikConstraints[i]; + if (constraint.name == constraintName) return constraint; + } + return null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it multiple times. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + const transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + const constraint = transformConstraints[i]; + if (constraint.name == constraintName) return constraint; + } + return null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + const pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + const constraint = pathConstraints[i]; + if (constraint.name == constraintName) return constraint; + } + return null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPhysicsConstraint(constraintName) { + if (!constraintName) throw new Error("constraintName cannot be null."); + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) { + const constraint = physicsConstraints[i]; + if (constraint.name == constraintName) return constraint; + } + return null; + } + }; + + // spine-core/src/Skin.ts + var SkinEntry = class { + constructor(slotIndex = 0, name, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + }; + var Skin = class { + /** The skin's name, which is unique across all skins in the skeleton. */ + name; + attachments = new Array(); + bones = Array(); + constraints = new Array(); + /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ + color = new Color(0.99607843, 0.61960787, 0.30980393, 1); + // fe9e4fff + constructor(name) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + } + /** Adds an attachment to the skin for the specified slot index and name. */ + setAttachment(slotIndex, name, attachment) { + if (!attachment) throw new Error("attachment cannot be null."); + let attachments = this.attachments; + if (slotIndex >= attachments.length) attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (!attachment.attachment) continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + } + /** Returns the attachment for the specified slot index and name, or null. */ + getAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + } + /** Removes the attachment in the skin for the specified slot index and name, if any. */ + removeAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + if (dictionary) delete dictionary[name]; + } + /** Returns all attachments in this skin. */ + getAttachments() { + let entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + let slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + /** Returns all attachments in this skin for the specified slot index. */ + getAttachmentsForSlot(slotIndex, attachments) { + let slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + /** Clears all attachments, bones, and constraints. */ + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + let slot = skeleton.slots[i]; + let slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + let dictionary = oldSkin.attachments[slotIndex]; + for (let key in dictionary) { + let skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + let attachment = this.getAttachment(slotIndex, key); + if (attachment) slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } + }; + + // spine-core/src/SlotData.ts + var SlotData = class { + /** The index of the slot in {@link Skeleton#getSlots()}. */ + index = 0; + /** The name of the slot, which is unique across all slots in the skeleton. */ + name; + /** The bone this slot belongs to. */ + boneData; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ + attachmentName = null; + /** The blend mode for drawing the slot's attachment. */ + blendMode = 0 /* Normal */; + /** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = true; + constructor(index, name, boneData) { + if (index < 0) throw new Error("index must be >= 0."); + if (!name) throw new Error("name cannot be null."); + if (!boneData) throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + }; + var BlendMode = /* @__PURE__ */ ((BlendMode3) => { + BlendMode3[BlendMode3["Normal"] = 0] = "Normal"; + BlendMode3[BlendMode3["Additive"] = 1] = "Additive"; + BlendMode3[BlendMode3["Multiply"] = 2] = "Multiply"; + BlendMode3[BlendMode3["Screen"] = 3] = "Screen"; + return BlendMode3; + })(BlendMode || {}); + + // spine-core/src/TransformConstraintData.ts + var TransformConstraintData = class extends ConstraintData { + /** The bones that will be modified by this transform constraint. */ + bones = new Array(); + /** The target bone whose world transform will be copied to the constrained bones. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) throw new Error("BoneData not set."); + else return this._target; + } + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** An offset added to the constrained bone X translation. */ + offsetX = 0; + /** An offset added to the constrained bone Y translation. */ + offsetY = 0; + /** An offset added to the constrained bone scaleX. */ + offsetScaleX = 0; + /** An offset added to the constrained bone scaleY. */ + offsetScaleY = 0; + /** An offset added to the constrained bone shearY. */ + offsetShearY = 0; + relative = false; + local = false; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + attachmentLoader; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + skeletonData.name = ""; + let input = new BinaryInput(binary); + let lowHash = input.readInt32(); + let highHash = input.readInt32(); + skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + skeletonData.referenceScale = input.readFloat() * scale; + let nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let str = input.readString(); + if (!str) throw new Error("String in string table must not be null."); + input.strings.push(str); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let name = input.readString(); + if (!name) throw new Error("Bone name must not be null."); + let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + let data = new BoneData(i, name, parent); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.inherit = input.readByte(); + data.skinRequired = input.readBoolean(); + if (nonessential) { + Color.rgba8888ToColor(data.color, input.readInt32()); + data.icon = input.readString() ?? void 0; + data.visible = input.readBoolean(); + } + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let slotName = input.readString(); + if (!slotName) throw new Error("Slot name must not be null."); + let boneData = skeletonData.bones[input.readInt(true)]; + let data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.color, input.readInt32()); + let darkColor = input.readInt32(); + if (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + if (nonessential) data.visible = input.readBoolean(); + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) throw new Error("IK constraint data name must not be null."); + let data = new IkConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.bendDirection = (flags & 2) != 0 ? 1 : -1; + data.compress = (flags & 4) != 0; + data.stretch = (flags & 8) != 0; + data.uniform = (flags & 16) != 0; + if ((flags & 32) != 0) data.mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) data.softness = input.readFloat() * scale; + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) throw new Error("Transform constraint data name must not be null."); + let data = new TransformConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.local = (flags & 2) != 0; + data.relative = (flags & 4) != 0; + if ((flags & 8) != 0) data.offsetRotation = input.readFloat(); + if ((flags & 16) != 0) data.offsetX = input.readFloat() * scale; + if ((flags & 32) != 0) data.offsetY = input.readFloat() * scale; + if ((flags & 64) != 0) data.offsetScaleX = input.readFloat(); + if ((flags & 128) != 0) data.offsetScaleY = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) data.offsetShearY = input.readFloat(); + if ((flags & 2) != 0) data.mixRotate = input.readFloat(); + if ((flags & 4) != 0) data.mixX = input.readFloat(); + if ((flags & 8) != 0) data.mixY = input.readFloat(); + if ((flags & 16) != 0) data.mixScaleX = input.readFloat(); + if ((flags & 32) != 0) data.mixScaleY = input.readFloat(); + if ((flags & 64) != 0) data.mixShearY = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) throw new Error("Path constraint data name must not be null."); + let data = new PathConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + const flags = input.readByte(); + data.positionMode = flags & 1; + data.spacingMode = flags >> 1 & 3; + data.rotateMode = flags >> 3 & 3; + if ((flags & 128) != 0) data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == 0 /* Fixed */) data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) data.spacing *= scale; + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + const name = input.readString(); + if (!name) throw new Error("Physics constraint data name must not be null."); + const data = new PhysicsConstraintData(name); + data.order = input.readInt(true); + data.bone = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) data.x = input.readFloat(); + if ((flags & 4) != 0) data.y = input.readFloat(); + if ((flags & 8) != 0) data.rotate = input.readFloat(); + if ((flags & 16) != 0) data.scaleX = input.readFloat(); + if ((flags & 32) != 0) data.shearX = input.readFloat(); + data.limit = ((flags & 64) != 0 ? input.readFloat() : 5e3) * scale; + data.step = 1 / input.readUnsignedByte(); + data.inertia = input.readFloat(); + data.strength = input.readFloat(); + data.damping = input.readFloat(); + data.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + data.wind = input.readFloat(); + data.gravity = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) data.inertiaGlobal = true; + if ((flags & 2) != 0) data.strengthGlobal = true; + if ((flags & 4) != 0) data.dampingGlobal = true; + if ((flags & 8) != 0) data.massGlobal = true; + if ((flags & 16) != 0) data.windGlobal = true; + if ((flags & 32) != 0) data.gravityGlobal = true; + if ((flags & 64) != 0) data.mixGlobal = true; + data.mix = (flags & 128) != 0 ? input.readFloat() : 1; + skeletonData.physicsConstraints.push(data); + } + let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) { + let skin = this.readSkin(input, skeletonData, false, nonessential); + if (!skin) throw new Error("readSkin() should not have returned null."); + skeletonData.skins[i] = skin; + } + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + const skin = skeletonData.skins[linkedMesh.skinIndex]; + if (!linkedMesh.parent) throw new Error("Linked mesh parent must not be null"); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let eventName = input.readString(); + if (!eventName) throw new Error("Event data name must not be null"); + let data = new EventData(eventName); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let animationName = input.readString(); + if (!animationName) throw new Error("Animatio name must not be null."); + skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData)); + } + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) return null; + skin = new Skin("default"); + } else { + let skinName = input.readString(); + if (!skinName) throw new Error("Skin name must not be null."); + skin = new Skin(skinName); + if (nonessential) Color.rgba8888ToColor(skin.color, input.readInt32()); + skin.bones.length = input.readInt(true); + for (let i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.physicsConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let name = input.readStringRef(); + if (!name) + throw new Error("Attachment name must not be null"); + let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + if (attachment) skin.setAttachment(slotIndex, name, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + let scale = this.scale; + let flags = input.readByte(); + const name = (flags & 8) != 0 ? input.readStringRef() : attachmentName; + if (!name) throw new Error("Attachment name must not be null"); + switch (flags & 7) { + // BUG? + case 0 /* Region */: { + let path = (flags & 16) != 0 ? input.readStringRef() : null; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + let rotation = (flags & 128) != 0 ? input.readFloat() : 0; + let x = input.readFloat(); + let y = input.readFloat(); + let scaleX = input.readFloat(); + let scaleY = input.readFloat(); + let width = input.readFloat(); + let height = input.readFloat(); + if (!path) path = name; + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.sequence = sequence; + if (sequence == null) region.updateRegion(); + return region; + } + case 1 /* BoundingBox */: { + let vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) return null; + box.worldVerticesLength = vertices.length; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) Color.rgba8888ToColor(box.color, color); + return box; + } + case 2 /* Mesh */: { + let path = (flags & 16) != 0 ? input.readStringRef() : name; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const hullLength = input.readInt(true); + const vertices = this.readVertices(input, (flags & 128) != 0); + const uvs = this.readFloatArray(input, vertices.length, 1); + const triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3); + let edges = []; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input, input.readInt(true)); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertices.length; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + if (sequence == null) mesh.updateRegion(); + mesh.hullLength = hullLength << 1; + mesh.sequence = sequence; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case 3 /* LinkedMesh */: { + const path = (flags & 16) != 0 ? input.readStringRef() : name; + if (path == null) throw new Error("Path of linked mesh must not be null"); + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const inheritTimelines = (flags & 128) != 0; + const skinIndex = input.readInt(true); + const parent = input.readStringRef(); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.sequence = sequence; + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, parent, inheritTimelines)); + return mesh; + } + case 4 /* Path */: { + const closed2 = (flags & 16) != 0; + const constantSpeed = (flags & 32) != 0; + const vertices = this.readVertices(input, (flags & 64) != 0); + const lengths = Utils.newArray(vertices.length / 6, 0); + for (let i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + const color = nonessential ? input.readInt32() : 0; + const path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) return null; + path.closed = closed2; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertices.length; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) Color.rgba8888ToColor(path.color, color); + return path; + } + case 5 /* Point */: { + const rotation = input.readFloat(); + const x = input.readFloat(); + const y = input.readFloat(); + const color = nonessential ? input.readInt32() : 0; + const point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) Color.rgba8888ToColor(point.color, color); + return point; + } + case 6 /* Clipping */: { + const endSlotIndex = input.readInt(true); + const vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertices.length; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + } + readSequence(input) { + let sequence = new Sequence(input.readInt(true)); + sequence.start = input.readInt(true); + sequence.digits = input.readInt(true); + sequence.setupIndex = input.readInt(true); + return sequence; + } + readVertices(input, weighted) { + const scale = this.scale; + const vertexCount = input.readInt(true); + const vertices = new Vertices(); + vertices.length = vertexCount << 1; + if (!weighted) { + vertices.vertices = this.readFloatArray(input, vertices.length, scale); + return vertices; + } + let weights = new Array(); + let bonesArray = new Array(); + for (let i = 0; i < vertexCount; i++) { + let boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (let ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + } + readFloatArray(input, n, scale) { + let array = new Array(n); + if (scale == 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input, n) { + let array = new Array(n); + for (let i = 0; i < n; i++) + array[i] = input.readInt(true); + return array; + } + readAnimation(input, name, skeletonData) { + input.readInt(true); + let timelines = new Array(); + let scale = this.scale; + for (let i = 0, n = input.readInt(true); i < n; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + let timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + let bezierCount = input.readInt(true); + let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame == frameLast) break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + let bezierCount = input.readInt(true); + let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame == frameLast) break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + let bezierCount = input.readInt(true); + let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let na = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + let bezierCount = input.readInt(true); + let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame == frameLast) break; + let time2 = input.readFloat(); + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let type = input.readByte(), frameCount = input.readInt(true); + if (type == BONE_INHERIT) { + let timeline = new InheritTimeline(frameCount, boneIndex); + for (let frame = 0; frame < frameCount; frame++) { + timeline.setFrame(frame, input.readFloat(), input.readByte()); + } + timelines.push(timeline); + continue; + } + let bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_TRANSLATE: + timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEX: + timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEY: + timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_SCALE: + timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEX: + timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEY: + timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEAR: + timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARX: + timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARY: + timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let flags = input.readByte(); + let time = input.readFloat(), mix = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + let softness = (flags & 4) != 0 ? input.readFloat() * scale : 0; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); + if (frame == frameLast) break; + flags = input.readByte(); + const time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + const softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0; + if ((flags & 64) != 0) { + timeline.setStepped(frame); + } else if ((flags & 128) != 0) { + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true); + let data = skeletonData.pathConstraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case PATH_POSITION: + timelines.push(readTimeline1( + input, + new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data.positionMode == 0 /* Fixed */ ? scale : 1 + )); + break; + case PATH_SPACING: + timelines.push(readTimeline1( + input, + new PathConstraintSpacingTimeline(frameCount, bezierCount, index), + data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1 + )); + break; + case PATH_MIX: + let timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true) - 1; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true); + if (type == PHYSICS_RESET) { + const timeline = new PhysicsConstraintResetTimeline(frameCount, index); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat()); + timelines.push(timeline); + continue; + } + const bezierCount = input.readInt(true); + switch (type) { + case PHYSICS_INERTIA: + timelines.push(readTimeline1(input, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_STRENGTH: + timelines.push(readTimeline1(input, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_DAMPING: + timelines.push(readTimeline1(input, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MASS: + timelines.push(readTimeline1(input, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_WIND: + timelines.push(readTimeline1(input, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_GRAVITY: + timelines.push(readTimeline1(input, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MIX: + timelines.push(readTimeline1(input, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + let attachmentName = input.readStringRef(); + if (!attachmentName) throw new Error("attachmentName must not be null."); + let attachment = skin.getAttachment(slotIndex, attachmentName); + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + let vertexAttachment = attachment; + let weighted = vertexAttachment.bones; + let vertices = vertexAttachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let bezierCount = input.readInt(true); + let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end == 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = input.readInt(true); + end += start; + if (scale == 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame == frameLast) break; + let time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + let timeline = new SequenceTimeline(frameCount, slotIndex, attachment); + for (let frame = 0; frame < frameCount; frame++) { + let time = input.readFloat(); + let modeAndIndex = input.readInt32(); + timeline.setFrame( + frame, + time, + SequenceModeValues[modeAndIndex & 15], + modeAndIndex >> 4, + input.readFloat() + ); + } + timelines.push(timeline); + break; + } + } + } + } + } + let drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + let timeline = new DrawOrderTimeline(drawOrderCount); + let slotCount = skeletonData.slots.length; + for (let i = 0; i < drawOrderCount; i++) { + let time = input.readFloat(); + let offsetCount = input.readInt(true); + let drawOrder = Utils.newArray(slotCount, 0); + for (let ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + let unchanged = Utils.newArray(slotCount - offsetCount, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsetCount; ii++) { + let slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + } + let eventCount = input.readInt(true); + if (eventCount > 0) { + let timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + let time = input.readFloat(); + let eventData = skeletonData.events[input.readInt(true)]; + let event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readString(); + if (event.stringValue == null) event.stringValue = eventData.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + return new Animation(name, timelines, duration); + } + }; + var BinaryInput = class { + constructor(data, strings = new Array(), index = 0, buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + let value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + let value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + let index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + let charCount = 0; + for (let i = 0; i < byteCount; ) { + let b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + let value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() != 0; + } + }; + var LinkedMesh = class { + parent; + skinIndex; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skinIndex, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skinIndex = skinIndex; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + var Vertices = class { + constructor(bones = null, vertices = null, length = 0) { + this.bones = bones; + this.vertices = vertices; + this.length = length; + } + }; + function readTimeline1(input, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) break; + let time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; + } + function readTimeline2(input, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) break; + let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; + } + function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); + } + var BONE_ROTATE = 0; + var BONE_TRANSLATE = 1; + var BONE_TRANSLATEX = 2; + var BONE_TRANSLATEY = 3; + var BONE_SCALE = 4; + var BONE_SCALEX = 5; + var BONE_SCALEY = 6; + var BONE_SHEAR = 7; + var BONE_SHEARX = 8; + var BONE_SHEARY = 9; + var BONE_INHERIT = 10; + var SLOT_ATTACHMENT = 0; + var SLOT_RGBA = 1; + var SLOT_RGB = 2; + var SLOT_RGBA2 = 3; + var SLOT_RGB2 = 4; + var SLOT_ALPHA = 5; + var ATTACHMENT_DEFORM = 0; + var ATTACHMENT_SEQUENCE = 1; + var PATH_POSITION = 0; + var PATH_SPACING = 1; + var PATH_MIX = 2; + var PHYSICS_INERTIA = 0; + var PHYSICS_STRENGTH = 1; + var PHYSICS_DAMPING = 2; + var PHYSICS_MASS = 4; + var PHYSICS_WIND = 5; + var PHYSICS_GRAVITY = 6; + var PHYSICS_MIX = 7; + var PHYSICS_RESET = 8; + var CURVE_STEPPED = 1; + var CURVE_BEZIER = 2; + + // spine-core/src/SkeletonBounds.ts + var SkeletonBounds = class { + /** The left edge of the axis aligned bounding box. */ + minX = 0; + /** The bottom edge of the axis aligned bounding box. */ + minY = 0; + /** The right edge of the axis aligned bounding box. */ + maxX = 0; + /** The top edge of the axis aligned bounding box. */ + maxY = 0; + /** The visible bounding boxes. */ + boundingBoxes = new Array(); + /** The world vertices for the bounding box polygons. */ + polygons = new Array(); + polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + /** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding + * box's polygon. + * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the + * SkeletonBounds AABB methods will always return true. */ + update(skeleton, updateAabb) { + if (!skeleton) throw new Error("skeleton cannot be null."); + let boundingBoxes = this.boundingBoxes; + let polygons = this.polygons; + let polygonPool = this.polygonPool; + let slots = skeleton.slots; + let slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + let slot = slots[i]; + if (!slot.bone.active) continue; + let attachment = slot.getAttachment(); + if (attachment instanceof BoundingBoxAttachment) { + let boundingBox = attachment; + boundingBoxes.push(boundingBox); + let polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + let vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + let x = vertices[ii]; + let y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + /** Returns true if the axis aligned bounding box contains the point. */ + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + /** Returns true if the axis aligned bounding box intersects the line segment. */ + aabbIntersectsSegment(x1, y1, x2, y2) { + let minX = this.minX; + let minY = this.minY; + let maxX = this.maxX; + let maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + let m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; + } + /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ + containsPoint(x, y) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains the point. */ + containsPointPolygon(polygon, x, y) { + let vertices = polygon; + let nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + let vertexY = vertices[ii + 1]; + let prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + let vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside; + } + prevIndex = ii; + } + return inside; + } + /** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns + * true. */ + intersectsSegment(x1, y1, x2, y2) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains any part of the line segment. */ + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + let vertices = polygon; + let nn = polygon.length; + let width12 = x1 - x2, height12 = y1 - y2; + let det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + let x4 = vertices[ii], y4 = vertices[ii + 1]; + let det2 = x3 * y4 - y3 * x4; + let width34 = x3 - x4, height34 = y3 - y4; + let det3 = width12 * height34 - height12 * width34; + let x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + let y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + /** Returns the polygon for the specified bounding box, or null. */ + getPolygon(boundingBox) { + if (!boundingBox) throw new Error("boundingBox cannot be null."); + let index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + } + /** The width of the axis aligned bounding box. */ + getWidth() { + return this.maxX - this.minX; + } + /** The height of the axis aligned bounding box. */ + getHeight() { + return this.maxY - this.minY; + } + }; + + // spine-core/src/Triangulator.ts + var Triangulator = class _Triangulator { + convexPolygons = new Array(); + convexPolygonsIndices = new Array(); + indicesArray = new Array(); + isConcaveArray = new Array(); + triangles = new Array(); + polygonPool = new Pool(() => { + return new Array(); + }); + polygonIndicesPool = new Pool(() => { + return new Array(); + }); + triangulate(verticesArray) { + let vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + let indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + let isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = _Triangulator.isConcave(i, vertexCount, vertices, indices); + let triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + let p1x = vertices[p1], p1y = vertices[p1 + 1]; + let p2x = vertices[p2], p2y = vertices[p2 + 1]; + let p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) continue; + let v = indices[ii] << 1; + let vx = vertices[v], vy = vertices[v + 1]; + if (_Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (_Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (_Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + let previousIndex = (vertexCount + i - 1) % vertexCount; + let nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = _Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = _Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + } + decompose(verticesArray, triangles) { + let vertices = verticesArray; + let convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + let convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + let x1 = vertices[t1], y1 = vertices[t1 + 1]; + let x2 = vertices[t2], y2 = vertices[t2 + 1]; + let x3 = vertices[t3], y3 = vertices[t3 + 1]; + let merged = false; + if (fanBaseIndex == t1) { + let o = polygon.length - 4; + let winding1 = _Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + let winding2 = _Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = _Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) continue; + let firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + let o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + let firstX = polygon[0], firstY = polygon[1]; + let secondX = polygon[2], secondY = polygon[3]; + let winding = _Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii == i) continue; + let otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) continue; + let otherFirstIndex = otherIndices[0]; + let otherSecondIndex = otherIndices[1]; + let otherLastIndex = otherIndices[2]; + let otherPoly = convexPolygons[ii]; + let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; + let winding1 = _Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + let winding2 = _Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + let current = indices[index] << 1; + let next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea( + vertices[previous], + vertices[previous + 1], + vertices[current], + vertices[current + 1], + vertices[next], + vertices[next + 1] + ); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + let px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + } + }; + + // spine-core/src/SkeletonClipping.ts + var SkeletonClipping = class _SkeletonClipping { + triangulator = new Triangulator(); + clippingPolygon = new Array(); + clipOutput = new Array(); + clippedVertices = new Array(); + clippedUVs = new Array(); + clippedTriangles = new Array(); + scratch = new Array(); + clipAttachment = null; + clippingPolygons = null; + clipStart(slot, clip) { + if (this.clipAttachment) return 0; + this.clipAttachment = clip; + let n = clip.worldVerticesLength; + let vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + let clippingPolygon = this.clippingPolygon; + _SkeletonClipping.makeClockwise(clippingPolygon); + let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) { + let polygon = clippingPolygons[i]; + _SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + } + clipEndWithSlot(slot) { + if (this.clipAttachment && this.clipAttachment.endSlot == slot.data) this.clipEnd(); + } + clipEnd() { + if (!this.clipAttachment) return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, verticesLengthOrTriangles, trianglesOrTrianglesLength, trianglesLengthOrUvs, uvsOrLight, lightOrDark, darkOrTwoColor, twoColorParam) { + let triangles; + let trianglesLength; + let uvs; + let light; + let dark; + let twoColor; + if (typeof verticesLengthOrTriangles === "number") { + triangles = trianglesOrTrianglesLength; + trianglesLength = trianglesLengthOrUvs; + uvs = uvsOrLight; + light = lightOrDark; + dark = darkOrTwoColor; + twoColor = twoColorParam; + } else { + triangles = verticesLengthOrTriangles; + trianglesLength = trianglesOrTrianglesLength; + uvs = trianglesLengthOrUvs; + light = uvsOrLight; + dark = lightOrDark; + twoColor = darkOrTwoColor; + } + if (uvs && light && dark && typeof twoColor === "boolean") + this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor); + else + this.clipTrianglesNoRender(vertices, triangles, trianglesLength); + } + clipTrianglesNoRender(vertices, triangles, trianglesLength) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) continue; + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let vertexSize = twoColor ? 12 : 8; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesUnpacked(vertices, triangles, trianglesLength, uvs) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices, clippedUVs = this.clippedUVs; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedUVs.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + let clippedUVsItems = Utils.setArraySize(clippedUVs, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedUVsItems[s] = u1 * a + u2 * b + u3 * c; + clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + let clippedUVSItems = Utils.setArraySize(clippedUVs, s + 3 * 2); + clippedUVSItems[s] = u1; + clippedUVSItems[s + 1] = v1; + clippedUVSItems[s + 2] = u2; + clippedUVSItems[s + 3] = v2; + clippedUVSItems[s + 4] = u3; + clippedUVSItems[s + 5] = v3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + clip(x1, y1, x2, y2, x3, y3, clippingArea, output) { + let originalOutput = output; + let clipped = false; + let input; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + let clippingVerticesLast = clippingArea.length - 4; + let clippingVertices = clippingArea; + for (let i = 0; ; i += 2) { + let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + let ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; + let outputStart = output.length; + let inputVertices = input; + for (let ii = 0, nn = input.length - 2; ii < nn; ) { + let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + ii += 2; + let inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; + let s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); + let s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); + if (s1 > 0) { + if (s2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } else if (s2) { + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + output.push(inputX2); + output.push(inputY2); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) break; + let temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + static makeClockwise(polygon) { + let vertices = polygon; + let verticeslength = polygon.length; + let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (let i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) return; + for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + let x = vertices[i], y = vertices[i + 1]; + let other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + } + }; + + // spine-core/src/SkeletonJson.ts + var SkeletonJson = class { + attachmentLoader; + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(json) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + let root = typeof json === "string" ? JSON.parse(json) : json; + let skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.referenceScale = getValue(skeletonMap, "referenceScale", 100) * scale; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images ?? null; + skeletonData.audioPath = skeletonMap.audio ?? null; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + let boneMap = root.bones[i]; + let parent = null; + let parentName = getValue(boneMap, "parent", null); + if (parentName) parent = skeletonData.findBone(parentName); + let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + data.x = getValue(boneMap, "x", 0) * scale; + data.y = getValue(boneMap, "y", 0) * scale; + data.rotation = getValue(boneMap, "rotation", 0); + data.scaleX = getValue(boneMap, "scaleX", 1); + data.scaleY = getValue(boneMap, "scaleY", 1); + data.shearX = getValue(boneMap, "shearX", 0); + data.shearY = getValue(boneMap, "shearY", 0); + data.inherit = Utils.enumValue(Inherit, getValue(boneMap, "inherit", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + let color = getValue(boneMap, "color", null); + if (color) data.color.setFromString(color); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + let slotMap = root.slots[i]; + let slotName = slotMap.name; + let boneData = skeletonData.findBone(slotMap.bone); + if (!boneData) throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`); + let data = new SlotData(skeletonData.slots.length, slotName, boneData); + let color = getValue(slotMap, "color", null); + if (color) data.color.setFromString(color); + let dark = getValue(slotMap, "dark", null); + if (dark) data.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + data.visible = getValue(slotMap, "visible", true); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (let i = 0; i < root.ik.length; i++) { + let constraintMap = root.ik[i]; + let data = new IkConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let bone = skeletonData.findBone(constraintMap.bones[ii]); + if (!bone) throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let target = skeletonData.findBone(constraintMap.target); + ; + if (!target) throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`); + data.target = target; + data.mix = getValue(constraintMap, "mix", 1); + data.softness = getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = getValue(constraintMap, "compress", false); + data.stretch = getValue(constraintMap, "stretch", false); + data.uniform = getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (let i = 0; i < root.transform.length; i++) { + let constraintMap = root.transform[i]; + let data = new TransformConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findBone(targetName); + if (!target) throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`); + data.target = target; + data.local = getValue(constraintMap, "local", false); + data.relative = getValue(constraintMap, "relative", false); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.offsetX = getValue(constraintMap, "x", 0) * scale; + data.offsetY = getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = getValue(constraintMap, "scaleY", 0); + data.offsetShearY = getValue(constraintMap, "shearY", 0); + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + data.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX); + data.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (let i = 0; i < root.path.length; i++) { + let constraintMap = root.path[i]; + let data = new PathConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findSlot(targetName); + if (!target) throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`); + data.target = target; + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.position = getValue(constraintMap, "position", 0); + if (data.positionMode == 0 /* Fixed */) data.position *= scale; + data.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) data.spacing *= scale; + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + skeletonData.pathConstraints.push(data); + } + } + if (root.physics) { + for (let i = 0; i < root.physics.length; i++) { + const constraintMap = root.physics[i]; + const data = new PhysicsConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + const boneName = constraintMap.bone; + const bone = skeletonData.findBone(boneName); + if (bone == null) throw new Error("Physics bone not found: " + boneName); + data.bone = bone; + data.x = getValue(constraintMap, "x", 0); + data.y = getValue(constraintMap, "y", 0); + data.rotate = getValue(constraintMap, "rotate", 0); + data.scaleX = getValue(constraintMap, "scaleX", 0); + data.shearX = getValue(constraintMap, "shearX", 0); + data.limit = getValue(constraintMap, "limit", 5e3) * scale; + data.step = 1 / getValue(constraintMap, "fps", 60); + data.inertia = getValue(constraintMap, "inertia", 1); + data.strength = getValue(constraintMap, "strength", 100); + data.damping = getValue(constraintMap, "damping", 1); + data.massInverse = 1 / getValue(constraintMap, "mass", 1); + data.wind = getValue(constraintMap, "wind", 0); + data.gravity = getValue(constraintMap, "gravity", 0); + data.mix = getValue(constraintMap, "mix", 1); + data.inertiaGlobal = getValue(constraintMap, "inertiaGlobal", false); + data.strengthGlobal = getValue(constraintMap, "strengthGlobal", false); + data.dampingGlobal = getValue(constraintMap, "dampingGlobal", false); + data.massGlobal = getValue(constraintMap, "massGlobal", false); + data.windGlobal = getValue(constraintMap, "windGlobal", false); + data.gravityGlobal = getValue(constraintMap, "gravityGlobal", false); + data.mixGlobal = getValue(constraintMap, "mixGlobal", false); + skeletonData.physicsConstraints.push(data); + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + let skinMap = root.skins[i]; + let skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) { + let boneName = skinMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) { + let constraintName = skinMap.ik[ii]; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) { + let constraintName = skinMap.transform[ii]; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) { + let constraintName = skinMap.path[ii]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.physics) { + for (let ii = 0; ii < skinMap.physics.length; ii++) { + let constraintName = skinMap.physics[ii]; + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (let slotName in skinMap.attachments) { + let slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); + let slotMap = skinMap.attachments[slotName]; + for (let entryName in slotMap) { + let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) throw new Error(`Skin not found: ${linkedMesh.skin}`); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (let eventName in root.events) { + let eventMap = root.events[eventName]; + let data = new EventData(eventName); + data.intValue = getValue(eventMap, "int", 0); + data.floatValue = getValue(eventMap, "float", 0); + data.stringValue = getValue(eventMap, "string", ""); + data.audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + data.volume = getValue(eventMap, "volume", 1); + data.balance = getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (let animationName in root.animations) { + let animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + } + readAttachment(map, skin, slotIndex, name, skeletonData) { + let scale = this.scale; + name = getValue(map, "name", name); + switch (getValue(map, "type", "region")) { + case "region": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + region.sequence = sequence; + let color = getValue(map, "color", null); + if (color) region.color.setFromString(color); + if (region.region != null) region.updateRegion(); + return region; + } + case "boundingbox": { + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) return null; + this.readVertices(map, box, map.vertexCount << 1); + let color = getValue(map, "color", null); + if (color) box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + let color = getValue(map, "color", null); + if (color) mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + mesh.sequence = sequence; + let parent = getValue(map, "parent", null); + if (parent) { + this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true))); + return mesh; + } + let uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + if (mesh.region != null) mesh.updateRegion(); + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + let vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + let color = getValue(map, "color", null); + if (color) path.color.setFromString(color); + return path; + } + case "point": { + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + let color = getValue(map, "color", null); + if (color) point.color.setFromString(color); + return point; + } + case "clipping": { + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) return null; + let end = getValue(map, "end", null); + if (end) clip.endSlot = skeletonData.findSlot(end); + let vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + let color = getValue(map, "color", null); + if (color) clip.color.setFromString(color); + return clip; + } + } + return null; + } + readSequence(map) { + if (map == null) return null; + let sequence = new Sequence(getValue(map, "count", 0)); + sequence.start = getValue(map, "start", 1); + sequence.digits = getValue(map, "digits", 0); + sequence.setupIndex = getValue(map, "setup", 0); + return sequence; + } + readVertices(map, attachment, verticesLength) { + let scale = this.scale; + attachment.worldVerticesLength = verticesLength; + let vertices = map.vertices; + if (verticesLength == vertices.length) { + let scaledVertices = Utils.toFloatArray(vertices); + if (scale != 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + let weights = new Array(); + let bones = new Array(); + for (let i = 0, n = vertices.length; i < n; ) { + let boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + readAnimation(map, name, skeletonData) { + let scale = this.scale; + let timelines = new Array(); + if (map.slots) { + for (let slotName in map.slots) { + let slotMap = map.slots[slotName]; + let slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error("Slot not found: " + slotName); + let slotIndex = slot.index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + if (!timelineMap) continue; + let frames = timelineMap.length; + if (timelineName == "attachment") { + let timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + let keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); + } + timelines.push(timeline); + } else if (timelineName == "rgba") { + let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb") { + let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "alpha") { + timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1)); + } else if (timelineName == "rgba2") { + let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb2") { + let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.bones) { + for (let boneName in map.bones) { + let boneMap = map.bones[boneName]; + let bone = skeletonData.findBone(boneName); + if (!bone) throw new Error("Bone not found: " + boneName); + let boneIndex = bone.index; + for (let timelineName in boneMap) { + let timelineMap = boneMap[timelineName]; + let frames = timelineMap.length; + if (frames == 0) continue; + if (timelineName === "rotate") { + timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1)); + } else if (timelineName === "translate") { + let timeline = new TranslateTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale)); + } else if (timelineName === "translatex") { + let timeline = new TranslateXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "translatey") { + let timeline = new TranslateYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "scale") { + let timeline = new ScaleTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1)); + } else if (timelineName === "scalex") { + let timeline = new ScaleXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "scaley") { + let timeline = new ScaleYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "shear") { + let timeline = new ShearTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1)); + } else if (timelineName === "shearx") { + let timeline = new ShearXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "sheary") { + let timeline = new ShearYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "inherit") { + let timeline = new InheritTimeline(frames, bone.index); + for (let frame = 0; frame < timelineMap.length; frame++) { + let aFrame = timelineMap[frame]; + timeline.setFrame(frame, getValue(aFrame, "time", 0), Utils.enumValue(Inherit, getValue(aFrame, "inherit", "Normal"))); + } + timelines.push(timeline); + } + } + } + } + if (map.ik) { + for (let constraintName in map.ik) { + let constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) continue; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) throw new Error("IK Constraint not found: " + constraintName); + let constraintIndex = skeletonData.ikConstraints.indexOf(constraint); + let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + let nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mix2 = getValue(nextMap, "mix", 1); + let softness2 = getValue(nextMap, "softness", 0) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (let constraintName in map.transform) { + let timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) throw new Error("Transform constraint not found: " + constraintName); + let constraintIndex = skeletonData.transformConstraints.indexOf(constraint); + let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1); + let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let mixScaleX2 = getValue(nextMap, "mixScaleX", 1); + let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2); + let mixShearY2 = getValue(nextMap, "mixShearY", 1); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (let constraintName in map.path) { + let constraintMap = map.path[constraintName]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) throw new Error("Path constraint not found: " + constraintName); + let constraintIndex = skeletonData.pathConstraints.indexOf(constraint); + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + let frames = timelineMap.length; + if (timelineName === "position") { + let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1)); + } else if (timelineName === "spacing") { + let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1)); + } else if (timelineName === "mix") { + let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.physics) { + for (let constraintName in map.physics) { + let constraintMap = map.physics[constraintName]; + let constraintIndex = -1; + if (constraintName.length > 0) { + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) throw new Error("Physics constraint not found: " + constraintName); + constraintIndex = skeletonData.physicsConstraints.indexOf(constraint); + } + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + let frames = timelineMap.length; + if (timelineName == "reset") { + const timeline2 = new PhysicsConstraintResetTimeline(frames, constraintIndex); + for (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++) + timeline2.setFrame(frame, getValue(keyMap, "time", 0)); + timelines.push(timeline2); + continue; + } + let timeline; + if (timelineName == "inertia") + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex); + else if (timelineName == "strength") + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex); + else if (timelineName == "damping") + timeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex); + else if (timelineName == "mass") + timeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex); + else if (timelineName == "wind") + timeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex); + else if (timelineName == "gravity") + timeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex); + else if (timelineName == "mix") + timeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex); + else + continue; + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } + } + } + if (map.attachments) { + for (let attachmentsName in map.attachments) { + let attachmentsMap = map.attachments[attachmentsName]; + let skin = skeletonData.findSkin(attachmentsName); + if (!skin) throw new Error("Skin not found: " + attachmentsName); + for (let slotMapName in attachmentsMap) { + let slotMap = attachmentsMap[slotMapName]; + let slot = skeletonData.findSlot(slotMapName); + if (!slot) throw new Error("Slot not found: " + slotMapName); + let slotIndex = slot.index; + for (let attachmentMapName in slotMap) { + let attachmentMap = slotMap[attachmentMapName]; + let attachment = skin.getAttachment(slotIndex, attachmentMapName); + for (let timelineMapName in attachmentMap) { + let timelineMap = attachmentMap[timelineMapName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + if (timelineMapName == "deform") { + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let curve = keyMap.curve; + if (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineMapName == "sequence") { + let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment); + let lastDelay = 0; + for (let frame = 0; frame < timelineMap.length; frame++) { + let delay = getValue(keyMap, "delay", lastDelay); + let time = getValue(keyMap, "time", 0); + let mode = SequenceMode[getValue(keyMap, "mode", "hold")]; + let index = getValue(keyMap, "index", 0); + timeline.setFrame(frame, time, mode, index, delay); + lastDelay = delay; + keyMap = timelineMap[frame + 1]; + } + timelines.push(timeline); + } + } + } + } + } + } + if (map.drawOrder) { + let timeline = new DrawOrderTimeline(map.drawOrder.length); + let slotCount = skeletonData.slots.length; + let frame = 0; + for (let i = 0; i < map.drawOrder.length; i++, frame++) { + let drawOrderMap = map.drawOrder[i]; + let drawOrder = null; + let offsets = getValue(drawOrderMap, "offsets", null); + if (offsets) { + drawOrder = Utils.newArray(slotCount, -1); + let unchanged = Utils.newArray(slotCount - offsets.length, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsets.length; ii++) { + let offsetMap = offsets[ii]; + let slot = skeletonData.findSlot(offsetMap.slot); + if (!slot) throw new Error("Slot not found: " + slot); + let slotIndex = slot.index; + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + } + if (map.events) { + let timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + let eventMap = map.events[i]; + let eventData = skeletonData.findEvent(eventMap.name); + if (!eventData) throw new Error("Event not found: " + eventMap.name); + let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + event.intValue = getValue(eventMap, "int", eventData.intValue); + event.floatValue = getValue(eventMap, "float", eventData.floatValue); + event.stringValue = getValue(eventMap, "string", eventData.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", 1); + event.balance = getValue(eventMap, "balance", 0); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + skeletonData.animations.push(new Animation(name, timelines, duration)); + } + }; + var LinkedMesh2 = class { + parent; + skin; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + function readTimeline12(keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value = getValue(keyMap, "value", defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let value2 = getValue(nextMap, "value", defaultValue) * scale; + if (keyMap.curve) bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + } + function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value1 = getValue(keyMap, name1, defaultValue) * scale; + let value2 = getValue(keyMap, name2, defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; + let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + } + function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve == "stepped") { + timeline.setStepped(frame); + return bezier; + } + let i = value << 2; + let cx1 = curve[i]; + let cy1 = curve[i + 1] * scale; + let cx2 = curve[i + 2]; + let cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; + } + function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; + } + + // spine-core/src/polyfills.ts + (() => { + if (typeof Math.fround === "undefined") { + Math.fround = /* @__PURE__ */ function(array) { + return function(x) { + return array[0] = x, array[0]; + }; + }(new Float32Array(1)); + } + })(); + + // spine-canvas/src/CanvasTexture.ts + var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-canvas/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new CanvasTexture(image); + }, pathPrefix, downloader); + } + }; + + // spine-canvas/src/SkeletonRenderer.ts + var worldVertices = Utils.newFloatArray(8); + var SkeletonRenderer = class _SkeletonRenderer { + static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + static VERTEX_SIZE = 2 + 2 + 4; + ctx; + triangleRendering = false; + debugRendering = false; + vertices = Utils.newFloatArray(8 * 1024); + tempColor = new Color(); + constructor(context) { + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) this.drawTriangles(skeleton); + else this.drawImages(skeleton); + } + drawImages(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + if (this.debugRendering) ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let bone = slot.bone; + if (!bone.active) continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof RegionAttachment)) continue; + attachment.computeWorldVertices(slot, worldVertices, 0, 2); + let region = attachment.region; + let image = region.texture.getImage(); + let slotColor = slot.color; + let regionColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * regionColor.r, + skeletonColor.g * slotColor.g * regionColor.g, + skeletonColor.b * slotColor.b * regionColor.b, + skeletonColor.a * slotColor.a * regionColor.a + ); + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + let 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; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h); + if (this.debugRendering) ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let attachment = slot.getAttachment(); + let texture; + let region; + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + texture = regionAttachment.region.texture.getImage(); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.texture.getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode != blendMode) blendMode = slot.data.blendMode; + let slotColor = slot.color; + let attachmentColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * attachmentColor.r, + skeletonColor.g * slotColor.g * attachmentColor.g, + skeletonColor.b * slotColor.b * attachmentColor.b, + skeletonColor.a * slotColor.a * attachmentColor.a + ); + 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; + 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]; + this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + // Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 + // Apache 2 licensed + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + let ctx = this.ctx; + const width = img.width - 1; + const height = img.height - 1; + u0 *= width; + v0 *= height; + u1 *= width; + v1 *= height; + u2 *= width; + v2 *= height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + let det = u1 * v2 - u2 * v1; + if (det == 0) return; + det = 1 / det; + const a = (v2 * x1 - v1 * x2) * det; + const b = (v2 * y1 - v1 * y2) * det; + const c = (u1 * x2 - u2 * x1) * det; + const d = (u1 * y2 - u2 * y1) * det; + const e = x0 - a * u0 - c * v0; + const f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = region.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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 + ); + region.computeWorldVertices(slot, this.vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let vertices = this.vertices; + let uvs = region.uvs; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = mesh.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let 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; + let vertices = this.vertices; + if (vertices.length < mesh.worldVerticesLength) this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + let uvs = mesh.uvs; + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } + }; + return __toCommonJS(index_exports); +})(); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/lib/4.3/spine-canvas.js b/release/MAC版本/lib/4.3/spine-canvas.js new file mode 100644 index 0000000..e7405c6 --- /dev/null +++ b/release/MAC版本/lib/4.3/spine-canvas.js @@ -0,0 +1,13723 @@ +"use strict"; +var spine = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // spine-canvas/src/index.ts + var index_exports = {}; + __export(index_exports, { + ATTACH_RETAIN: () => ATTACH_RETAIN, + ATTACH_SETUP: () => ATTACH_SETUP, + AlphaTimeline: () => AlphaTimeline, + Animation: () => Animation, + AnimationState: () => AnimationState, + AnimationStateAdapter: () => AnimationStateAdapter, + AnimationStateData: () => AnimationStateData, + AssetCache: () => AssetCache, + AssetManager: () => AssetManager, + AssetManagerBase: () => AssetManagerBase, + AtlasAttachmentLoader: () => AtlasAttachmentLoader, + Attachment: () => Attachment, + AttachmentTimeline: () => AttachmentTimeline, + BinaryInput: () => BinaryInput, + BlendMode: () => BlendMode, + Bone: () => Bone, + BoneData: () => BoneData, + BonePose: () => BonePose, + BoneTimeline1: () => BoneTimeline1, + BoneTimeline2: () => BoneTimeline2, + BoundingBoxAttachment: () => BoundingBoxAttachment, + CURRENT: () => CURRENT, + CanvasTexture: () => CanvasTexture, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + Constraint: () => Constraint, + ConstraintData: () => ConstraintData, + ConstraintTimeline1: () => ConstraintTimeline1, + CurveTimeline: () => CurveTimeline, + CurveTimeline1: () => CurveTimeline1, + DebugUtils: () => DebugUtils, + DeformTimeline: () => DeformTimeline, + Downloader: () => Downloader, + DrawOrder: () => DrawOrder, + DrawOrderFolderTimeline: () => DrawOrderFolderTimeline, + DrawOrderTimeline: () => DrawOrderTimeline, + Event: () => Event, + EventData: () => EventData, + EventQueue: () => EventQueue, + EventTimeline: () => EventTimeline, + EventType: () => EventType, + FIRST: () => FIRST, + FakeTexture: () => FakeTexture, + FromProperty: () => FromProperty, + FromRotate: () => FromRotate, + FromScaleX: () => FromScaleX, + FromScaleY: () => FromScaleY, + FromShearY: () => FromShearY, + FromX: () => FromX, + FromY: () => FromY, + HOLD: () => HOLD, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintPose: () => IkConstraintPose, + IkConstraintTimeline: () => IkConstraintTimeline, + Inherit: () => Inherit, + InheritTimeline: () => InheritTimeline, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + MODE: () => MODE, + MathUtils: () => MathUtils, + MeshAttachment: () => MeshAttachment, + MixFrom: () => MixFrom, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPose: () => PathConstraintPose, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + Physics: () => Physics, + PhysicsConstraint: () => PhysicsConstraint, + PhysicsConstraintDampingTimeline: () => PhysicsConstraintDampingTimeline, + PhysicsConstraintData: () => PhysicsConstraintData, + PhysicsConstraintGravityTimeline: () => PhysicsConstraintGravityTimeline, + PhysicsConstraintInertiaTimeline: () => PhysicsConstraintInertiaTimeline, + PhysicsConstraintMassTimeline: () => PhysicsConstraintMassTimeline, + PhysicsConstraintMixTimeline: () => PhysicsConstraintMixTimeline, + PhysicsConstraintPose: () => PhysicsConstraintPose, + PhysicsConstraintResetTimeline: () => PhysicsConstraintResetTimeline, + PhysicsConstraintStrengthTimeline: () => PhysicsConstraintStrengthTimeline, + PhysicsConstraintTimeline: () => PhysicsConstraintTimeline, + PhysicsConstraintWindTimeline: () => PhysicsConstraintWindTimeline, + PointAttachment: () => PointAttachment, + Pool: () => Pool, + Posed: () => Posed, + PosedActive: () => PosedActive, + PosedData: () => PosedData, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + Property: () => Property, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYMode: () => ScaleYMode, + ScaleYTimeline: () => ScaleYTimeline, + Sequence: () => Sequence, + SequenceMode: () => SequenceMode, + SequenceModeValues: () => SequenceModeValues, + SequenceTimeline: () => SequenceTimeline, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonJson: () => SkeletonJson, + SkeletonPhysicsMovement: () => SkeletonPhysicsMovement, + SkeletonRenderer: () => SkeletonRenderer, + SkeletonRendererCore: () => SkeletonRendererCore, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slider: () => Slider, + SliderData: () => SliderData, + SliderMixTimeline: () => SliderMixTimeline, + SliderPose: () => SliderPose, + SliderTimeline: () => SliderTimeline, + Slot: () => Slot, + SlotCurveTimeline: () => SlotCurveTimeline, + SlotData: () => SlotData, + SlotPose: () => SlotPose, + SpacingMode: () => SpacingMode, + StringSet: () => StringSet, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + ToProperty: () => ToProperty, + ToRotate: () => ToRotate, + ToScaleX: () => ToScaleX, + ToScaleY: () => ToScaleY, + ToShearY: () => ToShearY, + ToX: () => ToX, + ToY: () => ToY, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintPose: () => TransformConstraintPose, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + VertexAttachment: () => VertexAttachment, + WindowedMean: () => WindowedMean, + isBoneTimeline: () => isBoneTimeline, + isConstraintTimeline: () => isConstraintTimeline, + isSlotTimeline: () => isSlotTimeline + }); + + // spine-core/src/Utils.ts + var IntSet = class { + array = []; + add(value) { + const contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] !== void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } + }; + var StringSet = class { + entries = {}; + size = 0; + add(value) { + const contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + const oldSize = this.size; + for (let i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize !== this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } + }; + var Color = class _Color { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + static WHITE = new _Color(1, 1, 1, 1); + static RED = new _Color(1, 0, 0, 1); + static GREEN = new _Color(0, 1, 0, 1); + static BLUE = new _Color(0, 0, 1, 1); + static MAGENTA = new _Color(1, 0, 1, 1); + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) === "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length !== 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) this.r = 0; + else if (this.r > 1) this.r = 1; + if (this.g < 0) this.g = 0; + else if (this.g > 1) this.g = 1; + if (this.b < 0) this.b = 0; + else if (this.b > 1) this.b = 1; + if (this.a < 0) this.a = 0; + else if (this.a > 1) this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + toRgb888() { + const hex = (x) => `0${(x * 255).toString(16)}`.slice(-2); + return Number(`0x${hex(this.r)}${hex(this.g)}${hex(this.b)}`); + } + static fromString(hex, color = new _Color()) { + return color.setFromString(hex); + } + }; + var MathUtils = class _MathUtils { + static epsilon = 1e-5; + static epsilon2 = _MathUtils.epsilon * _MathUtils.epsilon; + // biome-ignore lint/suspicious/noApproximativeNumericConstant: reference runtime + static PI = 3.1415927; + static PI2 = _MathUtils.PI * 2; + static invPI2 = 1 / _MathUtils.PI2; + static radiansToDegrees = 180 / _MathUtils.PI; + static radDeg = _MathUtils.radiansToDegrees; + static degreesToRadians = _MathUtils.PI / 180; + static degRad = _MathUtils.degreesToRadians; + static clamp(value, min, max) { + if (value < min) return min; + if (value > max) return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static atan2Deg(y, x) { + return Math.atan2(y, x) * _MathUtils.radDeg; + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + const y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + const u = Math.random(); + const d = max - min; + if (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } + }; + var Interpolation = class _Interpolation { + static linear = new class extends _Interpolation { + applyInternal(a) { + return a; + } + }(); + /** Aka "smoothstep". */ + static smooth = new class extends _Interpolation { + applyInternal(a) { + return a * a * (3 - 2 * a); + } + }(); + /** Slow, then fast. */ + static slowFast = new class extends _Interpolation { + applyInternal(a) { + return a * a; + } + }(); + /** Fast, then slow. */ + static fastSlow = new class extends _Interpolation { + applyInternal(a) { + return (a - 1) * (a - 1) * -1 + 1; + } + }(); + static circle = new class extends _Interpolation { + applyInternal(a) { + if (a <= 0.5) { + a *= 2; + return (1 - Math.sqrt(1 - a * a)) / 2; + } + a--; + a *= 2; + return (Math.sqrt(1 - a * a) + 1) / 2; + } + }(); + apply(start, end, a) { + if (end === void 0 || a === void 0) return this.applyInternal(start); + return start + (end - start) * this.applyInternal(a); + } + }; + var Pow = class extends Interpolation { + power = 2; + constructor(power) { + super(); + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 === 0 ? -2 : 2) + 1; + } + }; + var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 === 0 ? -1 : 1) + 1; + } + }; + var Utils = class _Utils { + static SUPPORTS_TYPED_ARRAYS = typeof Float32Array !== "undefined"; + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case + static setArraySize(array, size, value = 0) { + const oldSize = array.length; + if (oldSize === size) return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) array[i] = value; + } + return array; + } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + const array = []; + for (let i = 0; i < size; i++) array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + const array = []; + for (let i = 0; i < array.length; i++) array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + const array = []; + for (let i = 0; i < array.length; i++) array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + // This function is used to fix WebKit 602 specific issue described at https://esotericsoftware.com/forum/d/10109-ios-10-disappearing-graphics + static webkit602BugfixHelper(alpha) { + } + static contains(array, element, identity = true) { + for (let i = 0; i < array.length; i++) + if (array[i] === element) return true; + return false; + } + // biome-ignore lint/suspicious/noExplicitAny: ok any in this case + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } + }; + var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + const bone = skeleton.bones[i].appliedPose; + console.log(`${bone.bone.data.name}, ${bone.a}, ${bone.b}, ${bone.c}, ${bone.d}, ${bone.worldX}, ${bone.worldY}`); + } + } + }; + var Pool = class { + items = []; + instantiator; + constructor(instantiator) { + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + item.reset?.(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } + }; + var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + const x = this.x; + const y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + const len = this.length(); + if (len !== 0) { + this.x /= len; + this.y /= len; + } + return this; + } + }; + var TimeKeeper = class { + maxDelta = 0.064; + framesPerSecond = 0; + delta = 0; + totalTime = 0; + lastTime = Date.now() / 1e3; + frameCount = 0; + frameTime = 0; + update() { + const now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } + }; + var WindowedMean = class { + values; + addedValues = 0; + lastValue = 0; + mean = 0; + dirty = true; + constructor(windowSize = 32) { + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } + }; + + // spine-core/src/Texture.ts + var Texture = class { + _image; + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } + }; + var TextureFilter = /* @__PURE__ */ ((TextureFilter2) => { + TextureFilter2[TextureFilter2["Nearest"] = 9728] = "Nearest"; + TextureFilter2[TextureFilter2["Linear"] = 9729] = "Linear"; + TextureFilter2[TextureFilter2["MipMap"] = 9987] = "MipMap"; + TextureFilter2[TextureFilter2["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter2[TextureFilter2["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter2[TextureFilter2["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter2[TextureFilter2["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + return TextureFilter2; + })(TextureFilter || {}); + var TextureWrap = /* @__PURE__ */ ((TextureWrap2) => { + TextureWrap2[TextureWrap2["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap2[TextureWrap2["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap2[TextureWrap2["Repeat"] = 10497] = "Repeat"; + return TextureWrap2; + })(TextureWrap || {}); + var TextureRegion = class { + texture; + u = 0; + v = 0; + u2 = 0; + v2 = 0; + width = 0; + height = 0; + degrees = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + }; + var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-core/src/TextureAtlas.ts + var TextureAtlas = class { + pages = []; + regions = []; + constructor(atlasText) { + const reader = new TextureAtlasReader(atlasText); + const entry = new Array(4); + const pageFields = {}; + pageFields.size = (page2) => { + page2.width = parseInt(entry[1]); + page2.height = parseInt(entry[2]); + }; + pageFields.format = () => { + }; + pageFields.filter = (page2) => { + page2.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page2.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields.repeat = (page2) => { + if (entry[1].indexOf("x") !== -1) page2.uWrap = 10497 /* Repeat */; + if (entry[1].indexOf("y") !== -1) page2.vWrap = 10497 /* Repeat */; + }; + pageFields.pma = (page2) => { + page2.pma = entry[1] === "true"; + }; + var regionFields = {}; + regionFields.xy = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields.size = (region) => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields.bounds = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields.offset = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields.orig = (region) => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields.offsets = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields.rotate = (region) => { + const value = entry[1]; + if (value === "true") + region.degrees = 90; + else if (value !== "false") + region.degrees = parseInt(value); + }; + regionFields.index = (region) => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length === 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length === 0) break; + if (reader.readEntry(entry, line) === 0) break; + line = reader.readLine(); + } + let page = null; + let names = null; + let values = null; + while (true) { + if (line === null) break; + if (line.trim().length === 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(line.trim()); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) === 0) break; + const field = pageFields[entry[0]]; + if (field) field(page); + } + this.pages.push(page); + } else { + const region = new TextureAtlasRegion(page, line); + while (true) { + const count = reader.readEntry(entry, line = reader.readLine()); + if (count === 0) break; + const field = regionFields[entry[0]]; + if (field) + field(region); + else { + if (!names) names = []; + if (!values) values = []; + names.push(entry[0]); + const entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth === 0 && region.originalHeight === 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0 && values && values.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees === 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name === name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (const page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture?.dispose(); + } + } + }; + var TextureAtlasReader = class { + lines; + index = 0; + constructor(text) { + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) return 0; + line = line.trim(); + if (line.length === 0) return 0; + const colon = line.indexOf(":"); + if (colon === -1) return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + const comma = line.indexOf(",", lastMatch); + if (comma === -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i === 4) return 4; + } + } + }; + var TextureAtlasPage = class { + name; + minFilter = 9728 /* Nearest */; + magFilter = 9728 /* Nearest */; + uWrap = 33071 /* ClampToEdge */; + vWrap = 33071 /* ClampToEdge */; + texture = null; + width = 0; + height = 0; + pma = false; + regions = []; + constructor(name) { + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + for (const region of this.regions) + region.texture = texture; + } + }; + var TextureAtlasRegion = class extends TextureRegion { + page; + name; + x = 0; + y = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + index = 0; + degrees = 0; + names = null; + values = null; + constructor(page, name) { + super(); + this.page = page; + this.name = name; + page.regions.push(this); + } + }; + + // spine-core/src/attachments/Attachment.ts + var Attachment = class _Attachment { + static empty = []; + name; + /** Timelines for the timeline attachment are also applied to this attachment. + * @return May be null if no attachment-specific timelines should be applied. */ + timelineAttachment; + /** Slots that can have attachments whose {@link timelineAttachment} is this attachment. */ + timelineSlots = _Attachment.empty; + constructor(name) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + this.timelineAttachment = this; + } + /** Returns true if the {@code slotIndex} or any {@link timelineSlots} have an attachment whose {@link timelineAttachment} is + * this attachment. + * @param slots The {@link Skeleton.slots}. + * @param slotIndex The timeline's primary slot index. */ + isTimelineActive(slots, slotIndex, appliedPose) { + let slot = slots[slotIndex]; + if (slot.bone.isActive()) { + const other = (appliedPose ? slot.getAppliedPose() : slot.getPose()).getAttachment(); + if (other != null && other.timelineAttachment === this) return true; + } + for (let i = 0, n = this.timelineSlots.length; i < n; i++) { + slot = slots[this.timelineSlots[i]]; + if (!slot.bone.isActive()) continue; + const other = (appliedPose ? slot.getAppliedPose() : slot.getPose()).getAttachment(); + if (other != null && other.timelineAttachment === this) return true; + } + return false; + } + }; + var VertexAttachment = class _VertexAttachment extends Attachment { + static nextID = 0; + /** The unique ID for this attachment. */ + id = _VertexAttachment.nextID++; + /** The bones that affect the {@link vertices}. The entries are, for each vertex, the number of bones affecting the vertex + * followed by that many bone indices, which is {@link Skeleton.getBones} index. Null if this attachment has no weights. */ + bones = null; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` triplets for each bone affecting + * each vertex. */ + vertices = []; + /** The maximum number of world vertex values that can be output by + * {@link computeWorldVertices} using the `count` parameter. */ + worldVerticesLength = 0; + constructor(name) { + super(name); + } + /** Transforms the attachment's local {@link vertices} to world coordinates. If {@link SlotPose.getDeform} is not empty, it + * is used to deform the vertices. + * + * See World transforms in the Spine + * Runtimes Guide. + * @param start The index of the first {@link vertices} value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= {@link worldVerticesLength} - `start`. + * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * + * `stride` / 2. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(skeleton, slot, start, count, worldVertices2, offset, stride) { + count = offset + (count >> 1) * stride; + const deformArray = slot.appliedPose.deform; + let vertices = this.vertices; + const bones = this.bones; + if (!bones) { + if (deformArray.length > 0) vertices = deformArray; + const bone = slot.bone.appliedPose; + const x = bone.worldX; + const y = bone.worldY; + const a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + const vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices2[w] = vx * a + vy * b + x; + worldVertices2[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + const n = bones[v]; + v += n + 1; + skip += n; + } + const skeletonBones = skeleton.bones; + if (deformArray.length === 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + const bone = skeletonBones[bones[v]].appliedPose; + const vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } else { + const deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + const bone = skeletonBones[bones[v]].appliedPose; + const vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } + } + /** Does not copy id (generated) or name (set on construction). **/ + copyTo(attachment) { + if (this.bones) { + attachment.bones = []; + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + attachment.timelineSlots = this.timelineSlots; + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class _MeshAttachment extends VertexAttachment { + sequence; + /** The UV pair for each vertex, normalized within the texture region. */ + regionUVs = []; + /** Triplets of vertex indices which describe the mesh's triangulation. */ + triangles = []; + /** The number of entries at the beginning of {@link vertices} that make up the mesh hull. */ + hullLength = 0; + /** The name of the texture region for this attachment. */ + path; + /** The color to tint the mesh. */ + color = new Color(1, 1, 1, 1); + sourceMesh = null; + /** Vertex index pairs describing edges for controlling triangulation, or null if nonessential data was not exported. Mesh + * triangles do not never cross edges. Triangulation is not performed at runtime. */ + edges = []; + /** The width of the mesh's image. Available only when nonessential data was exported. */ + width = 0; + /** The height of the mesh's image. Available only when nonessential data was exported. */ + height = 0; + tempColor = new Color(0, 0, 0, 0); + constructor(name, sequence) { + super(name); + this.sequence = sequence; + } + copy() { + if (this.sourceMesh) return this.newLinkedMesh(); + const copy = new _MeshAttachment(this.name, this.sequence.copy()); + copy.path = this.path; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = []; + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.triangles = []; + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + if (this.edges) { + copy.edges = []; + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + updateSequence() { + this.sequence.update(this); + } + /** The source mesh if this is a linked mesh, else null. A linked mesh shares the {@link bones}, {@link vertices}, + * {@link regionUVs}, {@link triangles}, {@link hullLength}, {@link edges}, {@link width}, and {@link height} with the + * source mesh, but may have a different {@link name} or {@link path}, and therefore a different texture region. */ + getSourceMesh() { + return this.sourceMesh; + } + setSourceMesh(sourceMesh) { + this.sourceMesh = sourceMesh; + if (sourceMesh) { + this.bones = sourceMesh.bones; + this.vertices = sourceMesh.vertices; + this.worldVerticesLength = sourceMesh.worldVerticesLength; + this.regionUVs = sourceMesh.regionUVs; + this.triangles = sourceMesh.triangles; + this.hullLength = sourceMesh.hullLength; + this.worldVerticesLength = sourceMesh.worldVerticesLength; + this.edges = sourceMesh.edges; + this.width = sourceMesh.width; + this.height = sourceMesh.height; + } + } + /** Returns a new mesh with the {@link sourceMesh} set to this mesh's source mesh, if any, else to this mesh. **/ + newLinkedMesh() { + const copy = new _MeshAttachment(this.name, this.sequence.copy()); + copy.timelineAttachment = this.timelineAttachment; + copy.path = this.path; + copy.color.setFromColor(this.color); + copy.setSourceMesh(this.sourceMesh ? this.sourceMesh : this); + copy.updateSequence(); + return copy; + } + /** Computes {@link Sequence.getUVs | UVs} for a mesh attachment. + * @param uvs Output array for the computed UVs, same length as regionUVs. */ + static computeUVs(region, regionUVs, uvs) { + if (!region) throw new Error("Region not set."); + const n = uvs.length; + let u = region.u, v = region.v, width = 0, height = 0; + if (region instanceof TextureAtlasRegion) { + const page = region.page; + const textureWidth = page.width, textureHeight = page.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + default: + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } + } else if (!region) { + u = v = 0; + width = height = 1; + } else { + width = region.u2 - u; + height = region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + }; + + // spine-core/src/attachments/RegionAttachment.ts + var RegionAttachment = class _RegionAttachment extends Attachment { + sequence; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The width of the region attachment in Spine. */ + width = 0; + /** The height of the region attachment in Spine. */ + height = 0; + /** The name of the texture region for this attachment. */ + path; + /** The color to tint the region attachment. */ + color = new Color(1, 1, 1, 1); + tempColor = new Color(1, 1, 1, 1); + constructor(name, sequence) { + super(name); + this.sequence = sequence; + } + copy() { + const copy = new _RegionAttachment(this.name, this.sequence.copy()); + copy.path = this.path; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + copy.color.setFromColor(this.color); + return copy; + } + /** Transforms the attachment's four vertices to world coordinates. + * + * See World transforms in the Spine + * Runtimes Guide. + * @param worldVertices The output world vertices. Must have a length >= `offset` + 8. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(slot, vertexOffsets, worldVertices2, offset, stride) { + const bone = slot.bone.appliedPose; + const x = bone.worldX, y = bone.worldY; + const a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = vertexOffsets[0]; + let offsetY = vertexOffsets[1]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffsets[2]; + offsetY = vertexOffsets[3]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffsets[4]; + offsetY = vertexOffsets[5]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffsets[6]; + offsetY = vertexOffsets[7]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + } + getOffsets(pose) { + return this.sequence.offsets[this.sequence.resolveIndex(pose)]; + } + updateSequence() { + this.sequence.update(this); + } + /** Computes {@link Sequence.getUVs | UVs} and {@link Sequence.getOffsets | offsets} for a region attachment. + * @param uvs Output array for the computed UVs, length of 8. + * @param offset Output array for the computed vertex offsets, length of 8. */ + static computeUVs(region, x, y, scaleX, scaleY, rotation, width, height, offset, uvs) { + if (!region) throw new Error("Region not set."); + const regionScaleX = width / region.originalWidth * scaleX; + const regionScaleY = height / region.originalHeight * scaleY; + const localX = -width / 2 * scaleX + region.offsetX * regionScaleX; + const localY = -height / 2 * scaleY + region.offsetY * regionScaleY; + const localX2 = localX + region.width * regionScaleX; + const localY2 = localY + region.height * regionScaleY; + const radians = rotation * MathUtils.degRad; + const cos = Math.cos(radians); + const sin = Math.sin(radians); + const localXCos = localX * cos + x; + const localXSin = localX * sin; + const localYCos = localY * cos + y; + const localYSin = localY * sin; + const localX2Cos = localX2 * cos + x; + const localX2Sin = localX2 * sin; + const localY2Cos = localY2 * cos + y; + const localY2Sin = localY2 * sin; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + if (region == null) { + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + uvs[4] = 1; + uvs[5] = 1; + uvs[6] = 1; + uvs[7] = 0; + } else { + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + if (region.degrees === 90) { + uvs[0] = region.u2; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[7] = region.v; + } else { + uvs[0] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[7] = region.v2; + } + } + } + static X1 = 0; + static Y1 = 1; + static C1R = 2; + static C1G = 3; + static C1B = 4; + static C1A = 5; + static U1 = 6; + static V1 = 7; + static X2 = 8; + static Y2 = 9; + static C2R = 10; + static C2G = 11; + static C2B = 12; + static C2A = 13; + static U2 = 14; + static V2 = 15; + static X3 = 16; + static Y3 = 17; + static C3R = 18; + static C3G = 19; + static C3B = 20; + static C3A = 21; + static U3 = 22; + static V3 = 23; + static X4 = 24; + static Y4 = 25; + static C4R = 26; + static C4G = 27; + static C4B = 28; + static C4A = 29; + static U4 = 30; + static V4 = 31; + }; + + // spine-core/src/attachments/Sequence.ts + var Sequence = class _Sequence { + static _nextID = 0; + id = _Sequence.nextID(); + /** The list of texture regions this sequence will display. */ + regions; + pathSuffix; + uvs; + /** Returns vertex offsets from the center of a {@link RegionAttachment}. Invalid to call for a {@link MeshAttachment}. */ + offsets; + /** The starting number for the numeric {@link getPath | path} suffix. */ + start = 0; + /** The minimum number of digits in the numeric {@link getPath | path} suffix, for zero padding. 0 for no zero + * padding. */ + digits = 0; + /** The index of the region to show for the setup pose. */ + setupIndex = 0; + /** @param count The number of texture regions this sequence will display. + * @param pathSuffix If true, the {@link getPath | path} has a numeric suffix. If false, all regions will use the + * same path, so `count` should be 1. */ + constructor(count, pathSuffix) { + this.regions = new Array(count); + this.pathSuffix = pathSuffix; + } + copy() { + const regionCount = this.regions.length; + const copy = new _Sequence(regionCount, this.pathSuffix); + Utils.arrayCopy(this.regions, 0, copy.regions, 0, regionCount); + copy.start = this.start; + copy.digits = this.digits; + copy.setupIndex = this.setupIndex; + if (this.uvs != null) { + const length = this.uvs[0].length; + copy.uvs = []; + for (let i = 0; i < regionCount; i++) { + copy.uvs[i] = Utils.newFloatArray(length); + Utils.arrayCopy(this.uvs[i], 0, copy.uvs[i], 0, length); + } + } + if (this.offsets != null) { + copy.offsets = []; + for (let i = 0; i < regionCount; i++) { + copy.offsets[i] = []; + Utils.arrayCopy(this.offsets[i], 0, copy.offsets[i], 0, 8); + } + } + return copy; + } + /** Computes UVs and offsets for the specified attachment. Must be called if the regions or attachment properties are + * changed. */ + update(attachment) { + const regionCount = this.regions.length; + if (attachment instanceof RegionAttachment) { + this.uvs = []; + this.offsets = []; + for (let i = 0; i < regionCount; i++) { + this.uvs[i] = Utils.newFloatArray(8); + this.offsets[i] = []; + RegionAttachment.computeUVs( + this.regions[i], + attachment.x, + attachment.y, + attachment.scaleX, + attachment.scaleY, + attachment.rotation, + attachment.width, + attachment.height, + this.offsets[i], + this.uvs[i] + ); + } + } else if (attachment instanceof MeshAttachment) { + const regionUVs = attachment.regionUVs; + this.uvs = []; + this.offsets = void 0; + for (let i = 0; i < regionCount; i++) { + this.uvs[i] = Utils.newFloatArray(regionUVs.length); + MeshAttachment.computeUVs(this.regions[i], regionUVs, this.uvs[i]); + } + } + } + /** Returns the {@link regions} index for the {@link SlotPose.getSequenceIndex}. */ + resolveIndex(pose) { + let index = pose.sequenceIndex; + if (index === -1) index = this.setupIndex; + if (index >= this.regions.length) index = this.regions.length - 1; + return index; + } + /** Returns the UVs for the specified index. {@link regions Regions} must be populated and {@link update} called + * before calling this method. */ + getUVs(index) { + return this.uvs[index]; + } + /** Returns true if the {@link getPath | path} has a numeric suffix. */ + hasPathSuffix() { + return this.pathSuffix; + } + /** Returns the specified base path with an optional numeric suffix for the specified index. */ + getPath(basePath, index) { + if (!this.pathSuffix) return basePath; + let result = basePath; + const frame = (this.start + index).toString(); + for (let i = this.digits - frame.length; i > 0; i--) + result += "0"; + result += frame; + return result; + } + static nextID() { + return _Sequence._nextID++; + } + }; + var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => { + SequenceMode2[SequenceMode2["hold"] = 0] = "hold"; + SequenceMode2[SequenceMode2["once"] = 1] = "once"; + SequenceMode2[SequenceMode2["loop"] = 2] = "loop"; + SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong"; + SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse"; + SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse"; + SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse"; + return SequenceMode2; + })(SequenceMode || {}); + var SequenceModeValues = [ + 0 /* hold */, + 1 /* once */, + 2 /* loop */, + 3 /* pingpong */, + 4 /* onceReverse */, + 5 /* loopReverse */, + 6 /* pingpongReverse */ + ]; + + // spine-core/src/Animation.ts + var Animation = class { + /** The animation's name, unique across all animations in the skeleton. + * + * See {@link SkeletonData.findAnimation}. */ + name; + /** The duration of the animation in seconds, which is usually the highest time of all frames in the timelines. The duration is + * used to know when the animation has completed and, for animations that repeat, when it should loop back to the start. */ + timelines = []; + timelineIds; + /** {@link Skeleton.getBones} indices that this animation's timelines modify. + * + * See {@link BoneTimeline.bones}. */ + bones; + // Nonessential. + /** The color of the animation as it was in Spine, or a default color if nonessential data was not exported. */ + color = new Color(1, 1, 1, 1); + /** The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is + * used to know when it has completed and when it should loop back to the start. */ + duration; + constructor(name, timelines, duration) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + this.duration = duration; + this.timelineIds = new StringSet(); + this.bones = []; + this.setTimelines(timelines); + } + setTimelines(timelines) { + if (!timelines) throw new Error("timelines cannot be null."); + this.timelines = timelines; + const n = timelines.length; + this.timelineIds.clear(); + this.bones.length = 0; + const boneSet = /* @__PURE__ */ new Set(); + const items = timelines; + for (let i = 0; i < n; i++) { + const timeline = items[i]; + this.timelineIds.addAll(timeline.propertyIds); + if (isBoneTimeline(timeline) && boneSet.add(timeline.boneIndex)) + this.bones.push(timeline.boneIndex); + } + } + /** Returns true if this animation contains a timeline with any of the specified property IDs. + * + * See {@link Timeline.propertyIds}. */ + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) return true; + return false; + } + /** Applies the animation's timelines to the specified skeleton. + * + * See {@link Timeline.apply} and + * Applying Animations in the Spine Runtimes + * Guide. + * @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton + * components the timelines may change. + * @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in which + * case all keys are triggered between `lastTime` (exclusive) and `time` (inclusive). Pass -1 + * the first time an animation is applied to ensure frame 0 is triggered. + * @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and + * interpolate between the frame values. + * @param loop True if `time` beyond the {@link duration} repeats the animation, else the last frame is used. + * @param events If any events are fired, they are added to this list. Pass null to ignore fired events or if no timelines fire + * events. + * @param alpha 0 applies setup or current values (depending on `from`), 1 uses timeline values, and intermediate + * values interpolate between them. Adjusting `alpha` over time can mix an animation in or out. + * @param from Controls how `alpha` and `add` mix from current or setup pose values to timeline values. + * @param add If true, for timelines that support it, their values are added to the setup or current values (depending on + * `from`). + * @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant transitions. + * @param appliedPose True to modify {@link Posed.appliedPose}, else {@link Posed.pose} is modified. */ + apply(skeleton, lastTime, time, loop, events, alpha, from, add, out, appliedPose) { + if (!skeleton) throw new Error("skeleton cannot be null."); + if (loop && this.duration !== 0) { + time %= this.duration; + if (lastTime > 0) lastTime %= this.duration; + } + const timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose); + } + }; + var MixFrom = /* @__PURE__ */ ((MixFrom2) => { + MixFrom2[MixFrom2["current"] = 0] = "current"; + MixFrom2[MixFrom2["setup"] = 1] = "setup"; + MixFrom2[MixFrom2["first"] = 2] = "first"; + return MixFrom2; + })(MixFrom || {}); + var Property = /* @__PURE__ */ ((Property2) => { + Property2[Property2["rotate"] = 0] = "rotate"; + Property2[Property2["x"] = 1] = "x"; + Property2[Property2["y"] = 2] = "y"; + Property2[Property2["scaleX"] = 3] = "scaleX"; + Property2[Property2["scaleY"] = 4] = "scaleY"; + Property2[Property2["shearX"] = 5] = "shearX"; + Property2[Property2["shearY"] = 6] = "shearY"; + Property2[Property2["inherit"] = 7] = "inherit"; + Property2[Property2["rgb"] = 8] = "rgb"; + Property2[Property2["alpha"] = 9] = "alpha"; + Property2[Property2["rgb2"] = 10] = "rgb2"; + Property2[Property2["attachment"] = 11] = "attachment"; + Property2[Property2["deform"] = 12] = "deform"; + Property2[Property2["event"] = 13] = "event"; + Property2[Property2["drawOrder"] = 14] = "drawOrder"; + Property2[Property2["drawOrderFolder"] = 15] = "drawOrderFolder"; + Property2[Property2["ikConstraint"] = 16] = "ikConstraint"; + Property2[Property2["transformConstraint"] = 17] = "transformConstraint"; + Property2[Property2["pathConstraintPosition"] = 18] = "pathConstraintPosition"; + Property2[Property2["pathConstraintSpacing"] = 19] = "pathConstraintSpacing"; + Property2[Property2["pathConstraintMix"] = 20] = "pathConstraintMix"; + Property2[Property2["physicsConstraintInertia"] = 21] = "physicsConstraintInertia"; + Property2[Property2["physicsConstraintStrength"] = 22] = "physicsConstraintStrength"; + Property2[Property2["physicsConstraintDamping"] = 23] = "physicsConstraintDamping"; + Property2[Property2["physicsConstraintMass"] = 24] = "physicsConstraintMass"; + Property2[Property2["physicsConstraintWind"] = 25] = "physicsConstraintWind"; + Property2[Property2["physicsConstraintGravity"] = 26] = "physicsConstraintGravity"; + Property2[Property2["physicsConstraintMix"] = 27] = "physicsConstraintMix"; + Property2[Property2["physicsConstraintReset"] = 28] = "physicsConstraintReset"; + Property2[Property2["sequence"] = 29] = "sequence"; + Property2[Property2["sliderTime"] = 30] = "sliderTime"; + Property2[Property2["sliderMix"] = 31] = "sliderMix"; + return Property2; + })(Property || {}); + var Timeline = class { + propertyIds; + frames; + /** True if this timeline supports being applied additively. + * + * See the `add` parameter in {@link Timeline.apply}. */ + additive = false; + /** True if this timeline sets values instantaneously and does not support interpolation between frames. */ + instant = false; + constructor(frameCount, ...propertyIds) { + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + /** The number of values stored per frame. */ + getFrameEntries() { + return 1; + } + /** The number of frames in this timeline. */ + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + /** The duration of the timeline in seconds, which is usually the highest time of all frames in the timeline. */ + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + /** Linear search using the specified stride (default 1). + * @param time Must be >= the first value in `frames`. + * @return The index of the first value <= `time`. */ + static search(frames, time, step = 1) { + const n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) return i - step; + return n - step; + } + }; + function isSlotTimeline(obj) { + return typeof obj === "object" && obj !== null && typeof obj.slotIndex === "number"; + } + var CurveTimeline = class extends Timeline { + curves; + // type, x, y, ... + constructor(frameCount, bezierCount, ...propertyIds) { + super(frameCount, ...propertyIds); + this.curves = Utils.newFloatArray( + frameCount + bezierCount * 18 + /*BEZIER_SIZE*/ + ); + this.curves[frameCount - 1] = 1; + } + /** Sets the specified key frame to linear interpolation. */ + setLinear(frame) { + this.curves[frame] = 0; + } + /** Sets the specified key frame to stepped interpolation. */ + setStepped(frame) { + this.curves[frame] = 1; + } + /** Shrinks the storage for Bezier curves, for use when `bezierCount` (specified in the constructor) was larger + * than the actual number of Bezier curves. */ + shrink(bezierCount) { + const size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + const newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than + * one curve per frame. + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and `bezierCount - 1` (specified + * in the constructor), inclusive. + * @param frame Between 0 and `frameCount - 1`, inclusive. + * @param value The index of the value for this frame that this curve is used for. + * @param time1 The time for the first key. + * @param value1 The value for the first key. + * @param cx1 The time for the first Bezier handle. + * @param cy1 The value for the first Bezier handle. + * @param cx2 The time of the second Bezier handle. + * @param cy2 The value for the second Bezier handle. + * @param time2 The time for the second key. + * @param value2 The value for the second key. */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + const curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value === 0) curves[frame] = 2 + i; + const tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + const dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + /** Returns the Bezier interpolated value for the specified time. + * @param frameIndex The index into {@link frames} for the values of the frame before `time`. + * @param valueOffset The offset from `frameIndex` to the value this curve is used for. + * @param i The index of the Bezier segments. See {@link getCurveType}. */ + getBezierValue(time, frameIndex, valueOffset, i) { + const curves = this.curves; + if (curves[i] > time) { + const x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + const n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + const x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + const x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } + }; + var CurveTimeline1 = class _CurveTimeline1 extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, propertyId); + } + getFrameEntries() { + return 2; + } + /** Sets the time and value for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE*/ + ] = value; + } + /** Returns the interpolated value for the specified time. */ + getCurveValue(time) { + const frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + const curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: { + const before = frames[i], value = frames[ + i + 1 + /*VALUE*/ + ]; + return value + (time - before) / (frames[ + i + 2 + /*ENTRIES*/ + ] - before) * (frames[ + i + 2 + 1 + /*VALUE*/ + ] - value); + } + case 1: + return frames[ + i + 1 + /*VALUE*/ + ]; + } + return this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + } + /** Returns the interpolated value for properties relative to the setup value. The timeline value is added to the setup + * value, rather than replacing it. + * + * See {@link Timeline.apply}. + * @param current The current value for the property. + * @param setup The setup value for the property. */ + getRelativeValue(time, alpha, from, add, current, setup) { + if (time < this.frames[0]) return _CurveTimeline1.beforeFirstKey(from, alpha, current, setup); + const value = this.getCurveValue(time); + return from === 1 /* setup */ ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha; + } + getAbsoluteValue(time, alpha, from, add, current, setup, value) { + if (value === void 0) + return this.getAbsoluteValue1(time, alpha, from, add, current, setup); + else + return this.getAbsoluteValue2(time, alpha, from, add, current, setup, value); + } + getAbsoluteValue1(time, alpha, from, add, current, setup) { + if (time < this.frames[0]) return _CurveTimeline1.beforeFirstKey(from, alpha, current, setup); + const value = this.getCurveValue(time); + return from === 1 /* setup */ ? setup + (add ? value : value - setup) * alpha : current + (add ? value : value - current) * alpha; + } + getAbsoluteValue2(time, alpha, from, add, current, setup, value) { + if (time < this.frames[0]) return _CurveTimeline1.beforeFirstKey(from, alpha, current, setup); + return from === 1 /* setup */ ? setup + (add ? value : value - setup) * alpha : current + (add ? value : value - current) * alpha; + } + /** Returns the interpolated value for scale properties. The timeline and setup values are multiplied and sign adjusted. + * + * See {@link Timeline.apply}. + * @param current The current value for the property. + * @param setup The setup value for the property. */ + getScaleValue(time, alpha, from, add, out, current, setup) { + if (time < this.frames[0]) return _CurveTimeline1.beforeFirstKey(from, alpha, current, setup); + const value = this.getCurveValue(time) * setup; + if (alpha === 1 && !add) return value; + let base = from === 1 /* setup */ ? setup : current; + if (add) return base + (value - setup) * alpha; + if (out) return base + (Math.abs(value) * Math.sign(base) - base) * alpha; + base = Math.abs(base) * Math.sign(value); + return base + (value - base) * alpha; + } + static beforeFirstKey(from, alpha, current, setup) { + switch (from) { + case 1 /* setup */: + return setup; + case 2 /* first */: + return current + (setup - current) * alpha; + case 0 /* current */: + return current; + } + } + }; + function isBoneTimeline(obj) { + return typeof obj === "object" && obj !== null && typeof obj.boneIndex === "number"; + } + var BoneTimeline1 = class extends CurveTimeline1 { + boneIndex; + constructor(frameCount, bezierCount, boneIndex, property) { + super(frameCount, bezierCount, `${property}|${boneIndex}`); + this.boneIndex = boneIndex; + this.additive = true; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const bone = skeleton.bones[this.boneIndex]; + if (bone.active) + this.apply1(appliedPose ? bone.appliedPose : bone.pose, bone.data.setupPose, time, alpha, from, add, out); + } + }; + var BoneTimeline2 = class extends CurveTimeline { + boneIndex; + /** @param bezierCount The maximum number of Bezier curves. See {@link shrink}. + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + constructor(frameCount, bezierCount, boneIndex, property1, property2) { + super(frameCount, bezierCount, `${property1}|${boneIndex}`, `${property2}|${boneIndex}`); + this.boneIndex = boneIndex; + this.additive = true; + } + getFrameEntries() { + return 3; + } + /** Sets the time and values for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE1*/ + ] = value1; + this.frames[ + frame + 2 + /*VALUE2*/ + ] = value2; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const bone = skeleton.bones[this.boneIndex]; + if (bone.active) + this.apply1(appliedPose ? bone.appliedPose : bone.pose, bone.data.setupPose, time, alpha, from, add, out); + } + }; + var RotateTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 0 /* rotate */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.rotation = this.getRelativeValue(time, alpha, from, add, pose.rotation, setup.rotation); + } + }; + var TranslateTimeline = class extends BoneTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 1 /* x */, 2 /* y */); + } + apply1(pose, setup, time, alpha, from, add, out) { + const frames = this.frames; + if (time < frames[0]) { + switch (from) { + case 1 /* setup */: + pose.x = setup.x; + pose.y = setup.y; + break; + case 2 /* first */: + pose.x += (setup.x - pose.x) * alpha; + pose.y += (setup.y - pose.y) * alpha; + break; + } + return; + } + let x = 0, y = 0; + const i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + const t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + } + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (from === 1 /* setup */) { + pose.x = setup.x + x * alpha; + pose.y = setup.y + y * alpha; + } else if (add) { + pose.x += x * alpha; + pose.y += y * alpha; + } else { + pose.x += (setup.x + x - pose.x) * alpha; + pose.y += (setup.y + y - pose.y) * alpha; + } + } + }; + var TranslateXTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 1 /* x */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.x = this.getRelativeValue(time, alpha, from, add, pose.x, setup.x); + } + }; + var TranslateYTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 2 /* y */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.y = this.getRelativeValue(time, alpha, from, add, pose.y, setup.y); + } + }; + var ScaleTimeline = class extends BoneTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 3 /* scaleX */, 4 /* scaleY */); + } + apply1(pose, setup, time, alpha, from, add, out) { + const frames = this.frames; + if (time < frames[0]) { + switch (from) { + case 1 /* setup */: + pose.scaleX = setup.scaleX; + pose.scaleY = setup.scaleY; + break; + case 2 /* first */: + pose.scaleX += (setup.scaleX - pose.scaleX) * alpha; + pose.scaleY += (setup.scaleY - pose.scaleY) * alpha; + break; + } + return; + } + let x, y; + const i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + const t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + } + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + x *= setup.scaleX; + y *= setup.scaleY; + if (alpha === 1 && !add) { + pose.scaleX = x; + pose.scaleY = y; + } else { + let bx = 0, by = 0; + if (from === 1 /* setup */) { + bx = setup.scaleX; + by = setup.scaleY; + } else { + bx = pose.scaleX; + by = pose.scaleY; + } + if (add) { + pose.scaleX = bx + (x - setup.scaleX) * alpha; + pose.scaleY = by + (y - setup.scaleY) * alpha; + } else if (out) { + pose.scaleX = bx + (Math.abs(x) * Math.sign(bx) - bx) * alpha; + pose.scaleY = by + (Math.abs(y) * Math.sign(by) - by) * alpha; + } else { + bx = Math.abs(bx) * Math.sign(x); + by = Math.abs(by) * Math.sign(y); + pose.scaleX = bx + (x - bx) * alpha; + pose.scaleY = by + (y - by) * alpha; + } + } + } + }; + var ScaleXTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 3 /* scaleX */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.scaleX = this.getScaleValue(time, alpha, from, add, out, pose.scaleX, setup.scaleX); + } + }; + var ScaleYTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 4 /* scaleY */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.scaleY = this.getScaleValue(time, alpha, from, add, out, pose.scaleY, setup.scaleY); + } + }; + var ShearTimeline = class extends BoneTimeline2 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 5 /* shearX */, 6 /* shearY */); + } + apply1(pose, setup, time, alpha, from, add, out) { + const frames = this.frames; + if (time < frames[0]) { + switch (from) { + case 1 /* setup */: + pose.shearX = setup.shearX; + pose.shearY = setup.shearY; + break; + case 2 /* first */: + pose.shearX += (setup.shearX - pose.shearX) * alpha; + pose.shearY += (setup.shearY - pose.shearY) * alpha; + break; + } + return; + } + let x = 0, y = 0; + const i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + const t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + } + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (from === 1 /* setup */) { + pose.shearX = setup.shearX + x * alpha; + pose.shearY = setup.shearY + y * alpha; + } else if (add) { + pose.shearX += x * alpha; + pose.shearY += y * alpha; + } else { + pose.shearX += (setup.shearX + x - pose.shearX) * alpha; + pose.shearY += (setup.shearY + y - pose.shearY) * alpha; + } + } + }; + var ShearXTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 5 /* shearX */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.shearX = this.getRelativeValue(time, alpha, from, add, pose.shearX, setup.shearX); + } + }; + var ShearYTimeline = class extends BoneTimeline1 { + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, boneIndex, 6 /* shearY */); + } + apply1(pose, setup, time, alpha, from, add, out) { + pose.shearY = this.getRelativeValue(time, alpha, from, add, pose.shearY, setup.shearY); + } + }; + var InheritTimeline = class extends Timeline { + boneIndex; + constructor(frameCount, boneIndex) { + super(frameCount, `${7 /* inherit */}|${boneIndex}`); + this.boneIndex = boneIndex; + this.instant = true; + } + getFrameEntries() { + return 2; + } + /** Sets the inherit transform mode for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, inherit) { + frame *= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*INHERIT*/ + ] = inherit; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const bone = skeleton.bones[this.boneIndex]; + if (!bone.active) return; + const pose = appliedPose ? bone.appliedPose : bone.pose; + if (out) { + if (from !== 0 /* current */) pose.inherit = bone.data.setupPose.inherit; + } else { + const frames = this.frames; + if (time < frames[0]) { + if (from !== 0 /* current */) pose.inherit = bone.data.setupPose.inherit; + } else + pose.inherit = this.frames[ + Timeline.search( + frames, + time, + 2 + /*ENTRIES*/ + ) + 1 + /*INHERIT*/ + ]; + } + } + }; + var SlotCurveTimeline = class extends CurveTimeline { + slotIndex; + constructor(frameCount, bezierCount, slotIndex, ...propertyIds) { + super(frameCount, bezierCount, ...propertyIds); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const slot = skeleton.slots[this.slotIndex]; + if (slot.bone.active) this.apply1(slot, appliedPose ? slot.appliedPose : slot.pose, time, alpha, from, add); + } + }; + var RGBATimeline = class extends SlotCurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super( + frameCount, + bezierCount, + slotIndex, + // + `${8 /* rgb */}|${slotIndex}`, + // + `${9 /* alpha */}|${slotIndex}` + ); + } + getFrameEntries() { + return 5; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + } + apply1(slot, pose, time, alpha, from, add) { + const color = pose.color; + const frames = this.frames; + if (time < frames[0]) { + const setup = slot.data.setupPose.color; + switch (from) { + case 1 /* setup */: + color.setFromColor(setup); + break; + case 2 /* first */: + color.add( + (setup.r - color.r) * alpha, + (setup.g - color.g) * alpha, + (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha + ); + break; + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + const i = Timeline.search( + frames, + time, + 5 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 5 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + const t = (time - before) / (frames[ + i + 5 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 5 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 5 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 5 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 5 + 4 + /*A*/ + ] - a) * t; + break; + } + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + } + if (alpha === 1) + color.set(r, g, b, a); + else { + if (from === 1 /* setup */) { + const setup = slot.data.setupPose.color; + color.set( + setup.r + (r - setup.r) * alpha, + setup.g + (g - setup.g) * alpha, + setup.b + (b - setup.b) * alpha, + setup.a + (a - setup.a) * alpha + ); + } else + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } + }; + var RGBTimeline = class extends SlotCurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, slotIndex, `${8 /* rgb */}|${slotIndex}`); + } + getFrameEntries() { + return 4; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + } + apply1(slot, pose, time, alpha, from, add) { + const color = pose.color; + let r = 0, g = 0, b = 0; + const frames = this.frames; + if (time < frames[0]) { + const setup = slot.data.setupPose.color; + switch (from) { + case 1 /* setup */: { + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + break; + } + case 2 /* first */: { + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + break; + } + } + return; + } + const i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + const curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: { + const before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + const t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 4 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 4 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 4 + 3 + /*B*/ + ] - b) * t; + break; + } + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (alpha !== 1) { + if (from === 1 /* setup */) { + const setup = slot.data.setupPose.color; + r = setup.r + (r - setup.r) * alpha; + g = setup.g + (g - setup.g) * alpha; + b = setup.b + (b - setup.b) * alpha; + } else { + r = color.r + (r - color.r) * alpha; + g = color.g + (g - color.g) * alpha; + b = color.b + (b - color.b) * alpha; + } + } + color.r = r < 0 ? 0 : r > 1 ? 1 : r; + color.g = g < 0 ? 0 : g > 1 ? 1 : g; + color.b = b < 0 ? 0 : b > 1 ? 1 : b; + } + }; + var AlphaTimeline = class extends CurveTimeline1 { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, `${9 /* alpha */}|${slotIndex}`); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + const color = (appliedPose ? slot.appliedPose : slot.pose).color; + let a = 0; + const frames = this.frames; + if (time < frames[0]) { + const setup = slot.data.setupPose.color.a; + switch (from) { + case 1 /* setup */: + color.a = setup; + break; + case 2 /* first */: + color.a += (setup - color.a) * alpha; + break; + } + return; + } + a = this.getCurveValue(time); + if (alpha !== 1) { + if (from === 1 /* setup */) { + const setup = slot.data.setupPose.color; + a = setup.a + (a - setup.a) * alpha; + } else + a = color.a + (a - color.a) * alpha; + } + color.a = a < 0 ? 0 : a > 1 ? 1 : a; + } + }; + var RGBA2Timeline = class extends SlotCurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super( + frameCount, + bezierCount, + slotIndex, + // + `${8 /* rgb */}|${slotIndex}`, + // + `${9 /* alpha */}|${slotIndex}`, + // + `${10 /* rgb2 */}|${slotIndex}` + ); + } + getFrameEntries() { + return 8; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + this.frames[ + frame + 5 + /*R2*/ + ] = r2; + this.frames[ + frame + 6 + /*G2*/ + ] = g2; + this.frames[ + frame + 7 + /*B2*/ + ] = b2; + } + apply1(slot, pose, time, alpha, from, add) { + const light = pose.color, dark = pose.darkColor; + let r2 = 0, g2 = 0, b2 = 0; + const frames = this.frames; + if (time < frames[0]) { + const setup = slot.data.setupPose; + const setupLight = setup.color, setupDark = setup.darkColor; + switch (from) { + case 1 /* setup */: { + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + break; + } + case 2 /* first */: { + light.add( + (setupLight.r - light.r) * alpha, + (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha + ); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + break; + } + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + const i = Timeline.search( + frames, + time, + 8 + /*ENTRIES*/ + ); + const curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: { + const before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + const t = (time - before) / (frames[ + i + 8 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 8 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 8 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 8 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 8 + 4 + /*A*/ + ] - a) * t; + r2 += (frames[ + i + 8 + 5 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 8 + 6 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 8 + 7 + /*B2*/ + ] - b2) * t; + break; + } + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 7, + curveType + 18 * 6 - 2 + /*BEZIER*/ + ); + } + if (alpha === 1) + light.set(r, g, b, a); + else if (from === 1 /* setup */) { + const setupPose = slot.data.setupPose; + let setup = setupPose.color; + light.set( + setup.r + (r - setup.r) * alpha, + setup.g + (g - setup.g) * alpha, + setup.b + (b - setup.b) * alpha, + setup.a + (a - setup.a) * alpha + ); + setup = setupPose.darkColor; + r2 = setup.r + (r2 - setup.r) * alpha; + g2 = setup.g + (g2 - setup.g) * alpha; + b2 = setup.b + (b2 - setup.b) * alpha; + } else { + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + r2 = dark.r + (r2 - dark.r) * alpha; + g2 = dark.g + (g2 - dark.g) * alpha; + b2 = dark.b + (b2 - dark.b) * alpha; + } + dark.r = r2 < 0 ? 0 : r2 > 1 ? 1 : r2; + dark.g = g2 < 0 ? 0 : g2 > 1 ? 1 : g2; + dark.b = b2 < 0 ? 0 : b2 > 1 ? 1 : b2; + } + }; + var RGB2Timeline = class extends SlotCurveTimeline { + constructor(frameCount, bezierCount, slotIndex) { + super( + frameCount, + bezierCount, + slotIndex, + // + `${8 /* rgb */}|${slotIndex}`, + // + `${10 /* rgb2 */}|${slotIndex}` + ); + } + getFrameEntries() { + return 7; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*R2*/ + ] = r2; + this.frames[ + frame + 5 + /*G2*/ + ] = g2; + this.frames[ + frame + 6 + /*B2*/ + ] = b2; + } + apply1(slot, pose, time, alpha, from, add) { + const light = pose.color, dark = pose.darkColor; + let r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0; + const frames = this.frames; + if (time < frames[0]) { + const setup = slot.data.setupPose; + const setupLight = setup.color, setupDark = setup.darkColor; + switch (from) { + case 1 /* setup */: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + break; + case 2 /* first */: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + break; + } + return; + } + const i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + const t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 7 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 7 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 7 + 3 + /*B*/ + ] - b) * t; + r2 += (frames[ + i + 7 + 4 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 7 + 5 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 7 + 6 + /*B2*/ + ] - b2) * t; + break; + } + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (alpha !== 1) { + if (from === 1 /* setup */) { + const setupPose = slot.data.setupPose; + let setup = setupPose.color; + r = setup.r + (r - setup.r) * alpha; + g = setup.g + (g - setup.g) * alpha; + b = setup.b + (b - setup.b) * alpha; + setup = setupPose.darkColor; + r2 = setup.r + (r2 - setup.r) * alpha; + g2 = setup.g + (g2 - setup.g) * alpha; + b2 = setup.b + (b2 - setup.b) * alpha; + } else { + r = light.r + (r - light.r) * alpha; + g = light.g + (g - light.g) * alpha; + b = light.b + (b - light.b) * alpha; + r2 = dark.r + (r2 - dark.r) * alpha; + g2 = dark.g + (g2 - dark.g) * alpha; + b2 = dark.b + (b2 - dark.b) * alpha; + } + } + light.r = r < 0 ? 0 : r > 1 ? 1 : r; + light.g = g < 0 ? 0 : g > 1 ? 1 : g; + light.b = b < 0 ? 0 : b > 1 ? 1 : b; + dark.r = r2 < 0 ? 0 : r2 > 1 ? 1 : r2; + dark.g = g2 < 0 ? 0 : g2 > 1 ? 1 : g2; + dark.b = b2 < 0 ? 0 : b2 > 1 ? 1 : b2; + } + }; + var AttachmentTimeline = class extends Timeline { + slotIndex = 0; + /** The attachment name for each key frame. May contain null values to clear the attachment. */ + attachmentNames; + constructor(frameCount, slotIndex) { + super(frameCount, `${11 /* attachment */}|${slotIndex}`); + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + this.instant = true; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the attachment name for the specified key frame. */ + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) return; + const pose = appliedPose ? slot.appliedPose : slot.pose; + if (out || time < this.frames[0]) { + if (from !== 0 /* current */) this.setAttachment(skeleton, pose, slot.data.attachmentName); + } else + this.setAttachment(skeleton, pose, this.attachmentNames[Timeline.search(this.frames, time)]); + } + setAttachment(skeleton, pose, attachmentName) { + pose.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } + }; + var DeformTimeline = class extends CurveTimeline { + slotIndex; + /** The attachment that will be deformed. + * + * See {@link VertexAttachment.getTimelineAttachment}. */ + attachment; + /** The vertices for each key frame. */ + vertices; + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, `${12 /* deform */}|${slotIndex}|${attachment.id}`); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + this.additive = true; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time and vertices for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. + * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + /** @param value1 Ignored (0 is used for a deform timeline). + * @param value2 Ignored (1 is used for a deform timeline). */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + const curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value === 0) curves[frame] = 2 + i; + const tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + const dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + const curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: { + const x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + } + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + const x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + const n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + const x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + const x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const slots = skeleton.slots; + if (!this.attachment.isTimelineActive(slots, this.slotIndex, appliedPose)) return; + const timelineSlots = this.attachment.timelineSlots; + const frames = this.frames; + if (time < frames[0]) { + this.applyBeforeFirst(slots[this.slotIndex], appliedPose, alpha, from); + for (const slotIndex of timelineSlots) + this.applyBeforeFirst(slots[slotIndex], appliedPose, alpha, from); + return; + } + let v1, v2; + let percent; + if (time >= frames[frames.length - 1]) { + percent = 0; + v1 = this.vertices[frames.length - 1]; + v2 = null; + } else { + const frame = Timeline.search(frames, time); + percent = this.getCurvePercent(time, frame); + v1 = this.vertices[frame]; + v2 = this.vertices[frame + 1]; + } + const vertexCount = this.vertices[0].length; + this.applyToSlot(slots[this.slotIndex], appliedPose, v1, v2, percent, vertexCount, alpha, from, add); + for (const slotIndex of timelineSlots) + this.applyToSlot(slots[slotIndex], appliedPose, v1, v2, percent, vertexCount, alpha, from, add); + } + applyBeforeFirst(slot, appliedPose, alpha, from) { + if (!slot.bone.active) return; + const pose = appliedPose ? slot.appliedPose : slot.pose; + if (pose.attachment == null || pose.attachment.timelineAttachment !== this.attachment) return; + const deformArray = pose.deform; + if (deformArray.length === 0) from = 1 /* setup */; + switch (from) { + case 1 /* setup */: + deformArray.length = 0; + break; + case 2 /* first */: { + if (alpha === 1) { + deformArray.length = 0; + return; + } + const vertexCount = this.vertices[0].length; + deformArray.length = vertexCount; + const deform = deformArray; + const vertexAttachment = pose.attachment; + if (vertexAttachment.bones === null) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (let i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + } + } + applyToSlot(slot, appliedPose, v1, v2, percent, vertexCount, alpha, from, add) { + if (!slot.bone.active) return; + const pose = appliedPose ? slot.appliedPose : slot.pose; + if (pose.attachment === null || pose.attachment.timelineAttachment !== this.attachment) return; + const vertexAttachment = pose.attachment; + const deform = pose.deform; + if (deform.length === 0) from = 1 /* setup */; + const fromSetup = from === 1 /* setup */; + deform.length = vertexCount; + if (v2 === null) { + if (alpha === 1) { + if (add && !fromSetup) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) + deform[i] += v1[i] - setupVertices[i]; + } else { + for (let i = 0; i < vertexCount; i++) + deform[i] += v1[i]; + } + } else + Utils.arrayCopy(v1, 0, deform, 0, vertexCount); + } else if (fromSetup) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) { + const setup = setupVertices[i]; + deform[i] = setup + (v1[i] - setup) * alpha; + } + } else { + for (let i = 0; i < vertexCount; i++) + deform[i] = v1[i] * alpha; + } + } else if (add) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) + deform[i] += (v1[i] - setupVertices[i]) * alpha; + } else { + for (let i = 0; i < vertexCount; i++) + deform[i] += v1[i] * alpha; + } + } else { + for (let i = 0; i < vertexCount; i++) + deform[i] += (v1[i] - deform[i]) * alpha; + } + } else { + if (alpha === 1) { + if (add && !fromSetup) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] += prev + (v2[i] - prev) * percent - setupVertices[i]; + } + } else { + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] += prev + (v2[i] - prev) * percent; + } + } + } else if (percent === 0) + Utils.arrayCopy(v1, 0, deform, 0, vertexCount); + else { + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] = prev + (v2[i] - prev) * percent; + } + } + } else if (fromSetup) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i], setup = setupVertices[i]; + deform[i] = setup + (prev + (v2[i] - prev) * percent - setup) * alpha; + } + } else { + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] = (prev + (v2[i] - prev) * percent) * alpha; + } + } + } else if (add) { + if (!vertexAttachment.bones) { + const setupVertices = vertexAttachment.vertices; + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] += (prev + (v2[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] += (prev + (v2[i] - prev) * percent) * alpha; + } + } + } else { + for (let i = 0; i < vertexCount; i++) { + const prev = v1[i]; + deform[i] += (prev + (v2[i] - prev) * percent - deform[i]) * alpha; + } + } + } + } + }; + var SequenceTimeline = class _SequenceTimeline extends Timeline { + static ENTRIES = 3; + static MODE = 1; + static DELAY = 2; + slotIndex; + attachment; + constructor(frameCount, slotIndex, attachment) { + super(frameCount, `${29 /* sequence */}|${slotIndex}|${attachment.sequence.id}`); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.instant = true; + } + getFrameEntries() { + return _SequenceTimeline.ENTRIES; + } + getSlotIndex() { + return this.slotIndex; + } + /** The attachment for which the {@link SlotPose.sequenceIndex} will be set. + * + * See {@link VertexAttachment.timelineAttachment}. */ + getAttachment() { + return this.attachment; + } + /** Sets the time, mode, index, and frame time for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time Seconds between frames. */ + setFrame(frame, time, mode, index, delay) { + const frames = this.frames; + frame *= _SequenceTimeline.ENTRIES; + frames[frame] = time; + frames[frame + _SequenceTimeline.MODE] = mode | index << 4; + frames[frame + _SequenceTimeline.DELAY] = delay; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const slots = skeleton.slots; + if (!this.attachment.isTimelineActive(slots, this.slotIndex, appliedPose)) return; + const timelineSlots = this.attachment.timelineSlots; + const frames = this.frames; + if (out || time < frames[0]) { + if (from !== 0 /* current */) { + this.setupPose(slots[this.slotIndex], appliedPose); + for (const slotIndex of timelineSlots) + this.setupPose(slots[slotIndex], appliedPose); + } + return; + } + const i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES); + const before = frames[i]; + const modeAndIndex = frames[i + _SequenceTimeline.MODE]; + const delay = frames[i + _SequenceTimeline.DELAY]; + this.applyToSlot(slots[this.slotIndex], appliedPose, time, before, modeAndIndex, delay); + for (const slotIndex of timelineSlots) + this.applyToSlot(slots[slotIndex], appliedPose, time, before, modeAndIndex, delay); + } + setupPose(slot, appliedPose) { + if (!slot.bone.active) return; + const pose = appliedPose ? slot.appliedPose : slot.pose; + if (pose.attachment === null || pose.attachment.timelineAttachment !== this.attachment) return; + pose.sequenceIndex = -1; + } + applyToSlot(slot, appliedPose, time, before, modeAndIndex, delay) { + if (!slot.bone.active) return; + const pose = appliedPose ? slot.appliedPose : slot.pose; + if (pose.attachment === null || pose.attachment.timelineAttachment !== this.attachment) return; + let index = modeAndIndex >> 4, count = pose.attachment.sequence.regions.length; + const mode = SequenceModeValues[modeAndIndex & 15]; + if (mode !== 0 /* hold */) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case 1 /* once */: + index = Math.min(count - 1, index); + break; + case 2 /* loop */: + index %= count; + break; + case 3 /* pingpong */: { + const n = (count << 1) - 2; + index = n === 0 ? 0 : index % n; + if (index >= count) index = n - index; + break; + } + case 4 /* onceReverse */: + index = Math.max(count - 1 - index, 0); + break; + case 5 /* loopReverse */: + index = count - 1 - index % count; + break; + case 6 /* pingpongReverse */: { + const n = (count << 1) - 2; + index = n === 0 ? 0 : (index + count - 1) % n; + if (index >= count) index = n - index; + } + } + } + pose.sequenceIndex = index; + } + }; + var EventTimeline = class _EventTimeline extends Timeline { + static propertyIds = [`${13 /* event */}`]; + /** The event for each key frame. */ + events; + constructor(frameCount) { + super(frameCount, ..._EventTimeline.propertyIds); + this.events = new Array(frameCount); + this.instant = true; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the event for the specified key frame. */ + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + /** Fires events for frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + if (!firedEvents) return; + const frames = this.frames; + const frameCount = this.frames.length; + if (lastTime > time) { + this.apply(null, lastTime, Number.MAX_VALUE, firedEvents, 0, from, false, false, false); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search(frames, lastTime) + 1; + const frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] !== frameTime) break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } + }; + var DrawOrderTimeline = class _DrawOrderTimeline extends Timeline { + static propertyID = `${14 /* drawOrder */}`; + static propertyIds = [_DrawOrderTimeline.propertyID]; + /** The draw order for each key frame. See {@link setFrame}. */ + drawOrders; + constructor(frameCount) { + super(frameCount, ..._DrawOrderTimeline.propertyIds); + this.drawOrders = new Array(frameCount); + this.instant = true; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the draw order for the specified key frame. + * @param drawOrder Ordered {@link Skeleton.slots} indices, or null to use setup pose + * draw order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const pose = appliedPose ? skeleton.drawOrder.appliedPose : skeleton.drawOrder.pose; + const setup = skeleton.slots; + if (out || time < this.frames[0]) { + if (from !== 0 /* current */) Utils.arrayCopy(setup, 0, pose, 0, skeleton.slots.length); + return; + } + const order = this.drawOrders[Timeline.search(this.frames, time)]; + if (!order) + Utils.arrayCopy(setup, 0, pose, 0, skeleton.slots.length); + else { + for (let i = 0, n = order.length; i < n; i++) + pose[i] = setup[order[i]]; + } + } + }; + var DrawOrderFolderTimeline = class _DrawOrderFolderTimeline extends Timeline { + static propertyID = `${15 /* drawOrderFolder */}`; + slots; + inFolder; + drawOrders; + /** @param slots {@link Skeleton.slots} indices controlled by this timeline, in setup order. + * @param slotCount The maximum number of slots in the skeleton. */ + constructor(frameCount, slots, slotCount) { + super(frameCount, ..._DrawOrderFolderTimeline.propertyIds(slots)); + this.slots = slots; + this.drawOrders = new Array(frameCount); + this.inFolder = new Array(slotCount); + for (const i of slots) + this.inFolder[i] = true; + this.instant = true; + } + static propertyIds(slots) { + const n = slots.length; + const ids = new Array(n); + for (let i = 0; i < n; i++) + ids[i] = `${_DrawOrderFolderTimeline.propertyID}|${slots[i]}`; + return ids; + } + getFrameCount() { + return this.frames.length; + } + /** The {@link Skeleton.getSlots} indices that this timeline affects, in setup order. */ + getSlots() { + return this.slots; + } + /** The draw order for each frame. See {@link setFrame}. */ + getDrawOrders() { + return this.drawOrders; + } + /** Sets the time and draw order for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. + * @param drawOrder Ordered {@link getSlots} indices, or null to use setup pose order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, events, alpha, from, add, out, appliedPose) { + const pose = appliedPose ? skeleton.drawOrder.appliedPose : skeleton.drawOrder.pose; + const setup = skeleton.slots; + if (out || time < this.frames[0]) { + if (from !== 0 /* current */) this.setup(pose, setup); + } else { + const order = this.drawOrders[Timeline.search(this.frames, time)]; + if (!order) + this.setup(pose, setup); + else { + const inFolder = this.inFolder; + const slots = this.slots; + for (let i = 0, found = 0, done = slots.length; ; i++) { + if (inFolder[pose[i].data.index]) { + pose[i] = setup[slots[order[found]]]; + if (++found === done) break; + } + } + } + } + } + setup(pose, setup) { + const { inFolder, slots } = this; + for (let i = 0, found = 0, done = slots.length; ; i++) { + if (inFolder[pose[i].data.index]) { + pose[i] = setup[slots[found]]; + if (++found === done) break; + } + } + } + }; + function isConstraintTimeline(obj) { + return typeof obj === "object" && obj !== null && typeof obj.constraintIndex === "number"; + } + var IkConstraintTimeline = class extends CurveTimeline { + constraintIndex = 0; + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, `${16 /* ikConstraint */}|${constraintIndex}`); + this.constraintIndex = constraintIndex; + } + getFrameEntries() { + return 6; + } + /** Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. + * @param bendDirection 1 or -1. */ + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*MIX*/ + ] = mix; + this.frames[ + frame + 2 + /*SOFTNESS*/ + ] = softness; + this.frames[ + frame + 3 + /*BEND_DIRECTION*/ + ] = bendDirection; + this.frames[ + frame + 4 + /*COMPRESS*/ + ] = compress ? 1 : 0; + this.frames[ + frame + 5 + /*STRETCH*/ + ] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (!constraint.active) return; + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + const frames = this.frames; + if (time < frames[0]) { + const setup = constraint.data.setupPose; + switch (from) { + case 1 /* setup */: { + pose.mix = setup.mix; + pose.softness = setup.softness; + pose.bendDirection = setup.bendDirection; + pose.compress = setup.compress; + pose.stretch = setup.stretch; + break; + } + case 2 /* first */: { + pose.mix += (setup.mix - pose.mix) * alpha; + pose.softness += (setup.softness - pose.softness) * alpha; + pose.bendDirection = setup.bendDirection; + pose.compress = setup.compress; + pose.stretch = setup.stretch; + break; + } + } + return; + } + let mix = 0, softness = 0; + const i = Timeline.search( + frames, + time, + 6 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 6 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + const t = (time - before) / (frames[ + i + 6 + /*ENTRIES*/ + ] - before); + mix += (frames[ + i + 6 + 1 + /*MIX*/ + ] - mix) * t; + softness += (frames[ + i + 6 + 2 + /*SOFTNESS*/ + ] - softness) * t; + break; + } + case 1: + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + break; + default: + mix = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + softness = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + const base = from === 1 /* setup */ ? constraint.data.setupPose : pose; + pose.mix = base.mix + (mix - base.mix) * alpha; + pose.softness = base.softness + (softness - base.softness) * alpha; + if (out) { + if (from === 1 /* setup */) { + pose.bendDirection = base.bendDirection; + pose.compress = base.compress; + pose.stretch = base.stretch; + } + } else { + pose.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + pose.compress = frames[ + i + 4 + /*COMPRESS*/ + ] !== 0; + pose.stretch = frames[ + i + 5 + /*STRETCH*/ + ] !== 0; + } + } + }; + var TransformConstraintTimeline = class extends CurveTimeline { + /** The index of the transform constraint slot in {@link Skeleton.transformConstraints} that will be changed. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, `${17 /* transformConstraint */}|${constraintIndex}`); + this.constraintIndex = constraintIndex; + this.additive = true; + } + getFrameEntries() { + return 7; + } + /** Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + const frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + frames[ + frame + 4 + /*SCALEX*/ + ] = mixScaleX; + frames[ + frame + 5 + /*SCALEY*/ + ] = mixScaleY; + frames[ + frame + 6 + /*SHEARY*/ + ] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (!constraint.active) return; + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + const frames = this.frames; + if (time < frames[0]) { + const setup = constraint.data.setupPose; + switch (from) { + case 1 /* setup */: { + pose.mixRotate = setup.mixRotate; + pose.mixX = setup.mixX; + pose.mixY = setup.mixY; + pose.mixScaleX = setup.mixScaleX; + pose.mixScaleY = setup.mixScaleY; + pose.mixShearY = setup.mixShearY; + break; + } + case 2 /* first */: { + pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha; + pose.mixX += (setup.mixX - pose.mixX) * alpha; + pose.mixY += (setup.mixY - pose.mixY) * alpha; + pose.mixScaleX += (setup.mixScaleX - pose.mixScaleX) * alpha; + pose.mixScaleY += (setup.mixScaleY - pose.mixScaleY) * alpha; + pose.mixShearY += (setup.mixShearY - pose.mixShearY) * alpha; + break; + } + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + const i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + const curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: { + const before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + const t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 7 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 7 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 7 + 3 + /*Y*/ + ] - y) * t; + scaleX += (frames[ + i + 7 + 4 + /*SCALEX*/ + ] - scaleX) * t; + scaleY += (frames[ + i + 7 + 5 + /*SCALEY*/ + ] - scaleY) * t; + shearY += (frames[ + i + 7 + 6 + /*SHEARY*/ + ] - shearY) * t; + break; + } + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + scaleX = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + scaleY = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + shearY = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + const base = from === 1 /* setup */ ? constraint.data.setupPose : pose; + if (add) { + pose.mixRotate = base.mixRotate + rotate * alpha; + pose.mixX = base.mixX + x * alpha; + pose.mixY = base.mixY + y * alpha; + pose.mixScaleX = base.mixScaleX + scaleX * alpha; + pose.mixScaleY = base.mixScaleY + scaleY * alpha; + pose.mixShearY = base.mixShearY + shearY * alpha; + } else { + pose.mixRotate = base.mixRotate + (rotate - base.mixRotate) * alpha; + pose.mixX = base.mixX + (x - base.mixX) * alpha; + pose.mixY = base.mixY + (y - base.mixY) * alpha; + pose.mixScaleX = base.mixScaleX + (scaleX - base.mixScaleX) * alpha; + pose.mixScaleY = base.mixScaleY + (scaleY - base.mixScaleY) * alpha; + pose.mixShearY = base.mixShearY + (shearY - base.mixShearY) * alpha; + } + } + }; + var ConstraintTimeline1 = class extends CurveTimeline1 { + constraintIndex; + constructor(frameCount, bezierCount, constraintIndex, property) { + super(frameCount, bezierCount, `${property}|${constraintIndex}`); + this.constraintIndex = constraintIndex; + } + }; + var PathConstraintPositionTimeline = class extends ConstraintTimeline1 { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 18 /* pathConstraintPosition */); + this.additive = true; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (constraint.active) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + pose.position = this.getAbsoluteValue(time, alpha, from, add, pose.position, constraint.data.setupPose.position); + } + } + }; + var PathConstraintSpacingTimeline = class extends ConstraintTimeline1 { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 19 /* pathConstraintSpacing */); + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (constraint.active) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + pose.spacing = this.getAbsoluteValue( + time, + alpha, + from, + false, + pose.spacing, + constraint.data.setupPose.spacing + ); + } + } + }; + var PathConstraintMixTimeline = class extends CurveTimeline { + constraintIndex; + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, `${20 /* pathConstraintMix */}|${constraintIndex}`); + this.constraintIndex = constraintIndex; + } + getFrameEntries() { + return 4; + } + /** Sets the time and color for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, mixRotate, mixX, mixY) { + const frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (!constraint.active) return; + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + const frames = this.frames; + if (time < frames[0]) { + const setup = constraint.data.setupPose; + switch (from) { + case 1 /* setup */: { + pose.mixRotate = setup.mixRotate; + pose.mixX = setup.mixX; + pose.mixY = setup.mixY; + break; + } + case 2 /* first */: { + pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha; + pose.mixX += (setup.mixX - pose.mixX) * alpha; + pose.mixY += (setup.mixY - pose.mixY) * alpha; + break; + } + } + return; + } + let rotate, x, y; + const i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + const curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: { + const before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + const t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 4 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 4 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 4 + 3 + /*Y*/ + ] - y) * t; + break; + } + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + const base = from === 1 /* setup */ ? constraint.data.setupPose : pose; + if (add) { + pose.mixRotate = base.mixRotate + rotate * alpha; + pose.mixX = base.mixX + x * alpha; + pose.mixY = base.mixY + y * alpha; + } else { + pose.mixRotate = base.mixRotate + (rotate - base.mixRotate) * alpha; + pose.mixX = base.mixX + (x - base.mixX) * alpha; + pose.mixY = base.mixY + (y - base.mixY) * alpha; + } + } + }; + var PhysicsConstraintTimeline = class extends ConstraintTimeline1 { + /** @param constraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, bezierCount, constraintIndex, property) { + super(frameCount, bezierCount, constraintIndex, property); + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + if (add && !this.additive) add = false; + if (this.constraintIndex === -1) { + const value = time >= this.frames[0] ? this.getCurveValue(time) : 0; + const constraints = skeleton.physics; + for (const constraint of constraints) { + if (constraint.active && this.global(constraint.data)) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + this.set(pose, this.getAbsoluteValue(time, alpha, from, add, this.get(pose), this.get(constraint.data.setupPose), value)); + } + } + } else { + const constraint = skeleton.constraints[this.constraintIndex]; + if (constraint.active) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + this.set(pose, this.getAbsoluteValue(time, alpha, from, add, this.get(pose), this.get(constraint.data.setupPose))); + } + } + } + }; + var PhysicsConstraintInertiaTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 21 /* physicsConstraintInertia */); + } + get(pose) { + return pose.inertia; + } + set(pose, value) { + pose.inertia = value; + } + global(constraint) { + return constraint.inertiaGlobal; + } + }; + var PhysicsConstraintStrengthTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 22 /* physicsConstraintStrength */); + } + get(pose) { + return pose.strength; + } + set(pose, value) { + pose.strength = value; + } + global(constraint) { + return constraint.strengthGlobal; + } + }; + var PhysicsConstraintDampingTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 23 /* physicsConstraintDamping */); + } + get(pose) { + return pose.damping; + } + set(pose, value) { + pose.damping = value; + } + global(constraint) { + return constraint.dampingGlobal; + } + }; + var PhysicsConstraintMassTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 24 /* physicsConstraintMass */); + } + get(pose) { + return 1 / pose.massInverse; + } + set(pose, value) { + pose.massInverse = 1 / value; + } + global(constraint) { + return constraint.massGlobal; + } + }; + var PhysicsConstraintWindTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 25 /* physicsConstraintWind */); + this.additive = true; + } + get(pose) { + return pose.wind; + } + set(pose, value) { + pose.wind = value; + } + global(constraint) { + return constraint.windGlobal; + } + }; + var PhysicsConstraintGravityTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 26 /* physicsConstraintGravity */); + this.additive = true; + } + get(pose) { + return pose.gravity; + } + set(pose, value) { + pose.gravity = value; + } + global(constraint) { + return constraint.gravityGlobal; + } + }; + var PhysicsConstraintMixTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 27 /* physicsConstraintMix */); + } + get(pose) { + return pose.mix; + } + set(pose, value) { + pose.mix = value; + } + global(constraint) { + return constraint.mixGlobal; + } + }; + var PhysicsConstraintResetTimeline = class _PhysicsConstraintResetTimeline extends Timeline { + static propertyIds = [28 /* physicsConstraintReset */.toString()]; + /** The index of the physics constraint in {@link Skeleton.contraints} that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ + constraintIndex; + /** @param constraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, constraintIndex) { + super(frameCount, ..._PhysicsConstraintResetTimeline.propertyIds); + this.constraintIndex = constraintIndex; + this.instant = true; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time for the specified frame. + * @param frame Between 0 and `frameCount`, inclusive. */ + setFrame(frame, time) { + this.frames[frame] = time; + } + /** Resets the physics constraint when frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + let constraint; + if (this.constraintIndex !== -1) { + constraint = skeleton.constraints[this.constraintIndex]; + if (!constraint.active) return; + } + const frames = this.frames; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, from, false, false, false); + lastTime = -1; + } else if (lastTime >= frames[frames.length - 1]) + return; + if (time < frames[0]) return; + if (lastTime < frames[0] || time >= frames[Timeline.search(frames, lastTime) + 1]) { + if (constraint != null) + constraint.reset(skeleton); + else { + for (const constraint2 of skeleton.physics) { + if (constraint2.active) constraint2.reset(skeleton); + } + } + } + } + }; + var SliderTimeline = class extends ConstraintTimeline1 { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 30 /* sliderTime */); + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (constraint.active) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + pose.time = this.getAbsoluteValue(time, alpha, from, add, pose.time, constraint.data.setupPose.time); + } + } + }; + var SliderMixTimeline = class extends ConstraintTimeline1 { + constructor(frameCount, bezierCount, constraintIndex) { + super(frameCount, bezierCount, constraintIndex, 31 /* sliderMix */); + this.additive = true; + } + apply(skeleton, lastTime, time, firedEvents, alpha, from, add, out, appliedPose) { + const constraint = skeleton.constraints[this.constraintIndex]; + if (constraint.active) { + const pose = appliedPose ? constraint.appliedPose : constraint.pose; + pose.mix = this.getAbsoluteValue(time, alpha, from, add, pose.mix, constraint.data.setupPose.mix); + } + } + }; + + // spine-core/src/AnimationState.ts + var AnimationState = class _AnimationState { + static emptyAnimation = new Animation("", [], 0); + /** The AnimationStateData to look up mix durations. */ + data; + /** The list of tracks that have had animations. May contain null entries for tracks that currently have no animation. */ + tracks = []; + /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + * or faster. Defaults to 1. + * + * See {@link TrackEntry.timeScale} to affect a single animation. */ + timeScale = 1; + unkeyedState = 0; + events = []; + listeners = []; + queue = new EventQueue(this); + propertyIds = /* @__PURE__ */ new Map(); + animationsChanged = false; + trackEntryPool = new Pool(() => new TrackEntry()); + constructor(data) { + this.data = data; + } + /** Increments each track entry {@link TrackEntry.trackTime}, setting queued animations as current if needed. */ + update(delta) { + delta *= this.timeScale; + const tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + const current = tracks[i]; + if (!current) continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + const nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale === 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setTrack(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + /** Returns true when all mixing from entries are complete. */ + updateMixingFrom(to, delta) { + const from = to.mixingFrom; + if (!from) return true; + const finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.nextTrackLast !== -1 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha === 0 || to.mixDuration === 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) from.mixingFrom.mixingTo = to; + if (from.totalAlpha === 0) { + for (let next = to; next.mixingTo != null; next = next.mixingTo) + next.keepHold = true; + } + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + /** Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple + * skeletons to pose them identically. + * @returns True if any animations were applied. */ + apply(skeleton) { + if (!skeleton) throw new Error("skeleton cannot be null."); + if (this.animationsChanged) this._animationsChanged(); + const events = this.events; + const tracks = this.tracks; + let applied = false; + for (let i = 0, n = tracks.length; i < n; i++) { + const current = tracks[i]; + if (!current || current.delay > 0) continue; + applied = true; + let alpha = current.alpha; + if (current.mixingFrom) + alpha *= this.applyMixingFrom(current, skeleton); + else if (current.trackTime >= current.trackEnd && !current.next) + alpha = 0; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + const timelines = current.animation.timelines; + const timelineCount = timelines.length; + if (i === 0 && alpha === 1) { + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(alpha); + const timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, 1 /* setup */, true); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, 1 /* setup */, false, false, false); + } + } else { + const timelineMode = current.timelineMode; + const retainAttachments = alpha >= current.alphaAttachmentThreshold; + const add = current.additive, shortestRotation = add || current.shortestRotation; + const firstFrame = !shortestRotation && current.timelinesRotation.length !== timelineCount << 1; + if (firstFrame) current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + const timeline = timelines[ii]; + const from = timelineMode[ii] & MODE; + if (!shortestRotation && timeline instanceof RotateTimeline) { + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, from, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline, skeleton, applyTime, from, retainAttachments); + } else { + Utils.webkit602BugfixHelper(alpha); + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, from, add, false, false); + } + } + } + if (current.reverse) this.eventsReverse(current, animationLast, animationTime); + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + const setupState = this.unkeyedState + ATTACH_SETUP; + const slots = skeleton.slots; + for (let i = 0, n = skeleton.slots.length; i < n; i++) { + const slot = slots[i]; + if (slot.attachmentState === setupState) { + const attachmentName = slot.data.attachmentName; + slot.pose.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton) { + const from = to.mixingFrom; + const fromMix = from.mixingFrom !== null ? this.applyMixingFrom(from, skeleton) : 1; + const mix = to.mix(); + const a = from.alpha * fromMix, keep = 1 - mix * to.alpha; + const alphaMix = a * (1 - mix), alphaHold = keep > 0 ? alphaMix / keep : a; + const timelines = from.animation.timelines; + const timelineCount = timelines.length; + const timelineMode = from.timelineMode; + const timelineHoldMix = from.timelineHoldMix; + const retainAttachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; + const add = from.additive, shortestRotation = add || from.shortestRotation; + const firstFrame = !shortestRotation && from.timelinesRotation.length !== timelineCount << 1; + if (firstFrame) from.timelinesRotation.length = timelineCount << 1; + const timelinesRotation = from.timelinesRotation; + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + const timeline = timelines[i]; + const mode = timelineMode[i]; + const mixFrom = mode & MODE; + let alpha = 0; + if ((mode & HOLD) !== 0) { + const holdMix = timelineHoldMix[i]; + alpha = holdMix == null ? alphaHold : alphaHold * (1 - holdMix.mix()); + } else { + if (!drawOrder && timeline instanceof DrawOrderTimeline && mixFrom === 0 /* current */) continue; + alpha = alphaMix; + } + from.totalAlpha += alpha; + if (!shortestRotation && timeline instanceof RotateTimeline) { + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, mixFrom, timelinesRotation, i << 1, firstFrame); + } else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline( + timeline, + skeleton, + applyTime, + mixFrom, + retainAttachments && alpha >= from.alphaAttachmentThreshold + ); + else { + const out = !drawOrder || !(timeline instanceof DrawOrderTimeline) || mixFrom === 0 /* current */; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, mixFrom, add, out, false); + } + } + if (from.reverse && mix < from.eventThreshold) this.eventsReverse(from, animationLast, animationTime); + if (to.mixDuration > 0) this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + /** Applies the attachment timeline and sets {@link Slot.attachmentState}. + * @param retain True if the attachment remains after apply, false if temporary for deform timelines. */ + applyAttachmentTimeline(timeline, skeleton, time, from, retain) { + const slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) return; + if (!retain && slot.attachmentState === this.unkeyedState + ATTACH_RETAIN) return; + let setup = time < timeline.frames[0]; + let name = null; + if (!setup) { + name = timeline.attachmentNames[Timeline.search(timeline.frames, time)]; + setup = !retain && name == null; + } + if (setup) { + if (from === 0 /* current */) return; + name = slot.data.attachmentName; + } + slot.pose.setAttachment(name == null ? null : skeleton.getAttachment(slot.data.index, name)); + if (retain) + slot.attachmentState = this.unkeyedState + ATTACH_RETAIN; + else if (!setup) + slot.attachmentState = this.unkeyedState + ATTACH_SETUP; + } + /** Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest + * the first time the mixing was applied. */ + applyRotateTimeline(timeline, skeleton, time, alpha, from, timelinesRotation, i, firstFrame) { + if (firstFrame) timelinesRotation[i] = 0; + if (alpha === 1) { + timeline.apply(skeleton, 0, time, null, 1, from, false, false, false); + return; + } + const bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) return; + const pose = bone.pose, setup = bone.data.setupPose; + const frames = timeline.frames; + let r1, r2; + if (time < frames[0]) { + switch (from) { + case 1 /* setup */: { + pose.rotation = setup.rotation; + return; + } + case 0 /* current */: { + return; + } + } + r1 = pose.rotation; + r2 = setup.rotation; + } else { + r1 = from === 1 /* setup */ ? setup.rotation : pose.rotation; + r2 = setup.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= Math.ceil(diff / 360 - 0.5) * 360; + if (diff === 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + const loops = lastTotal - lastTotal % 360; + total = diff + loops; + let current = diff >= 0, dir = lastTotal >= 0; + if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) !== MathUtils.signum(diff)) { + if (Math.abs(lastTotal - loops) > 180) { + total += 360 * MathUtils.signum(lastTotal); + dir = current; + } else if (loops !== 0) + total -= 360 * MathUtils.signum(lastTotal); + else + dir = current; + } + if (dir !== current) total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + pose.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + const animationStart = entry.animationStart, animationEnd = entry.animationEnd, duration = animationEnd - animationStart; + const reverse = entry.reverse; + let split = entry.trackLast % duration; + if (reverse) split = duration - split; + const events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + const event = events[i]; + if (event.time < split !== reverse) break; + if (event.time >= animationStart && event.time <= animationEnd) this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) { + if (duration === 0) + complete = true; + else { + const cycles = Math.floor(entry.trackTime / duration); + complete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration); + } + } else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) this.queue.complete(entry); + for (; i < n; i++) { + const event = events[i]; + if (event.time >= animationStart && event.time <= animationEnd) this.queue.event(entry, event); + } + } + eventsReverse(entry, animationLast, animationTime) { + const duration = entry.animation.duration, from = duration - animationLast, to = duration - animationTime; + const timelines = entry.animation.timelines; + for (let i = 0, n = entry.animation.timelines.length; i < n; i++) { + const eventTimeline = timelines[i]; + if (!(eventTimeline instanceof EventTimeline)) continue; + const timelineEvents = eventTimeline.events; + const frames = eventTimeline.frames; + const frameCount = frames.length; + if (from >= to) { + for (let ii = 0; ii < frameCount; ii++) { + if (frames[ii] < to) continue; + if (frames[ii] >= from) break; + this.events.push(timelineEvents[ii]); + } + } else { + for (let ii2 = 0; ii2 < frameCount; ii2++) { + if (frames[ii2] >= from) break; + this.events.push(timelineEvents[ii2]); + } + let ii = 0; + for (; ii < frameCount; ii++) + if (frames[ii] >= to) break; + for (; ii < frameCount; ii++) + this.events.push(timelineEvents[ii]); + } + } + } + /** Removes all animations from all tracks, leaving skeletons in their current pose. + * + * Usually you want to use {@link setEmptyAnimations} to mix the skeletons back to the setup pose, rather than leaving + * them in their current pose. */ + clearTracks() { + const oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + /** Removes all animations from the track, leaving skeletons in their current pose. + * + * Usually you want to use {@link setEmptyAnimation} to mix the skeletons back to the setup pose, rather than + * leaving them in their current pose. */ + clearTrack(trackIndex) { + if (trackIndex < 0) throw new Error("trackIndex must be >= 0."); + if (trackIndex >= this.tracks.length) return; + const current = this.tracks[trackIndex]; + if (!current) return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + const from = entry.mixingFrom; + if (!from) break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setTrack(index, current, interrupt) { + const from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + from.next = null; + if (interrupt) this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + setAnimation(trackIndex, animationNameOrAnimation, loop = false) { + if (typeof animationNameOrAnimation === "string") + return this.setAnimation1(trackIndex, animationNameOrAnimation, loop); + return this.setAnimation2(trackIndex, animationNameOrAnimation, loop); + } + setAnimation1(trackIndex, animationName, loop = false) { + const animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error(`Animation not found: ${animationName}`); + return this.setAnimation2(trackIndex, animation, loop); + } + /** Sets the current animation for a track, discarding any queued animations. + * + * If the formerly current track entry is for the same animation and was never applied to a skeleton, it is replaced (not mixed + * from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case {@link TrackEntry.getTrackEnd} determines when the track is cleared. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener.dispose} event occurs. */ + setAnimation2(trackIndex, animation, loop = false) { + if (trackIndex < 0) throw new Error("trackIndex must be >= 0."); + if (!animation) throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast === -1 && current.animation === animation) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + const entry = this.trackEntry(trackIndex, animation, loop, current); + this.setTrack(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + addAnimation(trackIndex, animationNameOrAnimation, loop = false, delay = 0) { + if (typeof animationNameOrAnimation === "string") + return this.addAnimation1(trackIndex, animationNameOrAnimation, loop, delay); + return this.addAnimation2(trackIndex, animationNameOrAnimation, loop, delay); + } + addAnimation1(trackIndex, animationName, loop = false, delay = 0) { + const animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw new Error(`Animation not found: ${animationName}`); + return this.addAnimation2(trackIndex, animation, loop, delay); + } + addAnimation2(trackIndex, animation, loop = false, delay = 0) { + if (trackIndex < 0) throw new Error("trackIndex must be >= 0."); + if (!animation) throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + const entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setTrack(trackIndex, entry, true); + this.queue.drain(); + if (delay < 0) delay = 0; + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) delay = Math.max(delay + last.getTrackComplete() - entry.mixDuration, 0); + } + entry.delay = delay; + return entry; + } + /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * {@link TrackEntry.mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either {@link setEmptyAnimation}, + * {@link setEmptyAnimations}, or {@link addEmptyAnimation}. Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still needs to be applied one more time to mix out, so the properties it was animating are reverted. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * {@link addAnimation} with the desired delay (an empty animation has a duration of 0) and on + * the returned track entry, set the {@link TrackEntry.setMixDuration}. Mixing from an empty animation causes the new + * animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value + * from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation. + * + * See Empty animations in the Spine + * Runtimes Guide. */ + setEmptyAnimation(trackIndex, mixDuration = 0) { + const entry = this.setAnimation(trackIndex, _AnimationState.emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * {@link TrackEntry.mixDuration}. If the track has no entries, it is equivalent to calling + * {@link setEmptyAnimation}. + * + * See {@link setEmptyAnimation} and + * Empty animations in the Spine Runtimes + * Guide. + * @param delay If > 0, sets {@link TrackEntry.delay}. If <= 0, the delay set is the duration of the previous track entry minus + * any mix duration plus the specified `delay` (ie the mix ends at (when `delay` = 0) or before + * (when `delay` < 0) the previous track entry duration). If the previous entry is looping, its next loop + * completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener.dispose} event occurs. */ + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + const entry = this.addAnimation(trackIndex, _AnimationState.emptyAnimation, false, delay); + if (delay <= 0) entry.delay = Math.max(entry.delay + entry.mixDuration - mixDuration, 0); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + * + * See Empty animations in the Spine + * Runtimes Guide. */ + setEmptyAnimations(mixDuration = 0) { + const oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + const current = this.tracks[i]; + if (current) this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + /** @param last May be null. */ + trackEntry(trackIndex, animation, loop, last) { + const entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.additive = false; + entry.reverse = false; + entry.shortestRotation = false; + entry.eventThreshold = 0; + entry.alphaAttachmentThreshold = 0; + entry.mixAttachmentThreshold = 0; + entry.mixDrawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.totalAlpha = 0; + entry.keepHold = false; + return entry; + } + /** Removes {@link TrackEntry.next} and all entries after it for the specified entry. */ + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + const tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + const track = tracks[i]; + if (!track) continue; + let entry = track; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + this.computeHold(entry, track); + entry = entry.mixingTo; + } while (entry); + } + this.propertyIds.clear(); + } + computeHold(entry, track) { + const timelines = entry.animation.timelines; + const timelinesCount = entry.animation.timelines.length; + const timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + const timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + const add = entry.additive, keepHold = entry.keepHold; + const to = entry.mixingTo; + for (let i = 0; i < timelinesCount; i++) { + const timeline = timelines[i]; + const ids = timeline.propertyIds; + const from = this.from(track, timeline, ids); + if (add && timeline.additive) { + timelineMode[i] = from; + continue; + } + let mode; + if (to === null || timeline.instant || to.additive && timeline.additive || !to.animation?.hasTimeline(ids)) + mode = from; + else { + mode = from | HOLD; + for (let next = to.mixingTo; next != null; next = next.mixingTo) { + if (next.additive && timeline.additive || !next.animation?.hasTimeline(ids)) { + if (next.mixDuration > 0) timelineHoldMix[i] = next; + break; + } + } + } + if (keepHold) mode = mode & ~HOLD | timelineMode[i] & HOLD; + timelineMode[i] = mode; + } + } + from(track, timeline, ids) { + const propertyIds = this.propertyIds; + let from = SETUP; + for (let i = 0, n = ids.length; i < n; i++) { + const owner = propertyIds.get(ids[i]); + if (owner === void 0) { + propertyIds.set(ids[i], track); + } else { + if (owner !== track) { + while (++i < n) + if (!propertyIds.has(ids[i])) propertyIds.set(ids[i], track); + return CURRENT; + } + from = FIRST; + } + } + if (timeline instanceof DrawOrderFolderTimeline) { + const first = propertyIds.get(DrawOrderTimeline.propertyID); + if (first != null) return first !== track ? CURRENT : FIRST; + } + return from; + } + /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */ + getTrack(trackIndex) { + if (trackIndex < 0) throw new Error("trackIndex must be >= 0."); + if (trackIndex >= this.tracks.length) return null; + return this.tracks[trackIndex]; + } + /** Adds a listener to receive events for all track entries. */ + addListener(listener) { + if (!listener) throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + /** Removes the listener added with {@link addListener}. */ + removeListener(listener) { + const index = this.listeners.indexOf(listener); + if (index >= 0) this.listeners.splice(index, 1); + } + /** Removes all listeners added with {@link addListener}. */ + clearListeners() { + this.listeners.length = 0; + } + /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. */ + clearListenerNotifications() { + this.queue.clear(); + } + }; + var TrackEntry = class { + /** The animation to apply for this track entry. */ + animation = null; + previous = null; + /** The animation queued to start after this animation, or null. `next` makes up a linked list. */ + next = null; + /** The track entry for the previous animation when mixing to this animation, or null if no mixing is currently occurring. + * When mixing from multiple animations, `mixingFrom` makes up a doubly linked list. */ + mixingFrom = null; + /** The track entry for the next animation when mixing from this animation, or null if no mixing is currently occurring. + * When mixing to multiple animations, `mixingTo` makes up a doubly linked list. */ + mixingTo = null; + /** The listener for events generated by this track entry, or null. + * + * A track entry returned from {@link AnimationState.setAnimation} is already the current animation + * for the track, so the callback for listener {@link AnimationStateListener.start} will not be called. */ + listener = null; + /** The index of the track where this track entry is either current or queued. + * + * See {@link AnimationState.getTrack}. */ + trackIndex = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ + loop = false; + /** When true, timelines in this animation that support additive have their values added to the setup or current pose values + * instead of replacing them. Additive can be set for a new track entry only before {@link AnimationState.apply} + * is next called. */ + additive = false; + /** If true, the animation will be applied in reverse. */ + reverse = false; + /** If true, mixing rotation between tracks always uses the shortest rotation direction. If the rotation is animated, the + * shortest rotation direction may change during the mix. + * + * If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest + * of the mix. Defaults to false. + * + * See {@link resetRotationDirections}. */ + shortestRotation = false; + keepHold = false; + /** When the interpolated mix percentage is less than the `eventThreshold` , event timelines are applied while + * this animation is being mixed out. Defaults to 0, so event timelines are not applied while this animation is being mixed + * out. */ + eventThreshold = 0; + /** When the interpolated mix percentage is less than the `mixAttachmentThreshold`, attachment timelines are + * applied while this animation is being mixed out. Defaults to 0, so attachment timelines are not applied while this + * animation is being mixed out. */ + mixAttachmentThreshold = 0; + /** When the computed alpha is greater than `alphaAttachmentThreshold`, attachment timelines are applied. The + * computed alpha includes {@link alpha} and the interpolated mix percentage. Defaults to 0, so attachment timelines are + * always applied. */ + alphaAttachmentThreshold = 0; + /** When the interpolated mix percentage is less than the `mixAttachmentThreshold`, attachment timelines are + * applied while this animation is being mixed out. Defaults to 0, so attachment timelines are not applied while this + * animation is being mixed out. */ + mixDrawOrderThreshold = 0; + /** The time in seconds for the first frame of this animation, both initially and after looping. Defaults to 0. + * + * When setting `animationStart` time, {@link animationLast} can be set to the same value to avoid firing events + * from the start of the animation. */ + animationStart = 0; + /** The time in seconds for the last frame of this animation. Past this time, non-looping animations hold the pose at this + * time while looping animations will loop back to {@link animationStart}. Defaults to the {@link Animation.duration}. */ + animationEnd = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. For example, when + * this animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) + * and `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this + * animation is applied. */ + animationLast = 0; + nextAnimationLast = 0; + /** Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry, + * `delay` postpones incrementing the {@link trackTime}. When this track entry is queued, `delay` is + * the time from the start of the previous animation to when this track entry will become the current track entry (ie when + * the previous track entry {@link trackTime} >= this track entry's `delay`). + * + * {@link timeScale} affects the delay. + * + * When passing `delay` <= 0 to {@link AnimationState.addAnimation} this + * `delay` is set using a mix duration from {@link AnimationStateData}. To change the {@link mixDuration} + * afterward, use {@link setMixDuration} so this `delay` is adjusted. */ + delay = 0; + /** The time in seconds this track entry has been the current track entry, starting at 0 and increasing forever. Compare to + * {@link getAnimationTime}, which is always between {@link animationStart} and {@link animationEnd}. + * + * The track time can be set to start the animation at a time other than 0, without affecting looping. When doing so, + * {@link animationLast} can be set to the same value to avoid firing events from the start of the animation. + * + * To set the time an animation starts and loops, use {@link animationStart} and {@link animationEnd}. */ + trackTime = 0; + trackLast = 0; + nextTrackLast = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * Usually you want to use {@link AnimationState.addEmptyAnimation} rather than have the animation + * abruptly cease being applied, leaving the current pose. */ + trackEnd = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * Values < 0 are not supported. To play an animation in reverse, use {@link reverse}. + * + * {@link mixTime} is not affected by track entry time scale, so {@link mixDuration} may need to be adjusted to match the + * animation speed. + * + * When using {@link AnimationState.addAnimation} with a `delay` <= 0, the + * {@link delay} is set using the mix duration from {@link AnimationState.data}, assuming time scale to be 1. If the time + * scale is not 1, the delay may need to be adjusted. + * + * See {@link AnimationState.timeScale} to affect all animations. */ + timeScale = 0; + /** Values < 1 mix this animation with the skeleton's current pose (either the setup pose or the pose from lower tracks). + * Defaults to 1, which overwrites the skeleton's current pose with this animation. + * + * Alpha should be 1 on track 0. + * + * See {@link getAlphaAttachmentThreshold}. */ + alpha = 0; + /** Seconds elapsed from 0 to the {@link mixDuration} when mixing from the previous animation to this animation. May + * be slightly more than `mixDuration` when the mix is complete. */ + mixTime = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + * {@link AnimationStateData.getMix} based on the animation before this animation (if any). + * + * A mix duration of 0 still needs to be applied one more time to mix out, so the the properties it was animating are + * reverted. A mix duration of 0 can be set at any time to end the mix on the next + * {@link AnimationState.update | update}. + * + * The `mixDuration` can be set manually rather than use the value from + * {@link AnimationStateData.getMix}. In that case, the `mixDuration` can be set for a new + * track entry only before {@link AnimationState.update} is next called. + * + * When using {@link AnimationState.addAnimation} with a `delay` <= 0, the + * {@link getDelay} is set using the mix duration from {@link AnimationState.data}. If `mixDuration` is set + * afterward, the delay needs to be adjusted: + * + *

+     * entry.mixDuration = 0.25;
+ * entry.delay = entry.previous.getTrackComplete() - entry.mixDuration + 0; + *
+ * + * Alternatively, use {@link setMixDuration} to set both the mix duration and recompute the delay:
+ * + *
+      entry.setMixDuration(0.25f, 0); // mixDuration, delay
+     * 
+ */ + mixDuration = 0; + totalAlpha = 0; + mixInterpolation = Interpolation.linear; + /** Sets both {@link getMixDuration} and {@link getDelay}. + * @param delay If > 0, sets {@link getDelay}. If <= 0, the delay set is the duration of the previous track entry minus + * the specified mix duration plus the specified `delay` (ie the mix ends at (when `delay` = + * 0) or before (when `delay` < 0) the previous track entry duration). If the previous entry is + * looping, its next loop completion is used instead of its duration. */ + setMixDuration(mixDuration, delay) { + this.mixDuration = mixDuration; + if (delay !== void 0) { + if (delay <= 0) delay = this.previous == null ? 0 : Math.max(delay + this.previous.getTrackComplete() - mixDuration, 0); + this.delay = delay; + } + } + /** The interpolation to apply to the mix percentage ({@link mixTime} / {@link mixDuration}) when mixing from the previous + * animation to this animation. Defaults to linear. */ + setMixInterpolation(mixInterpolation) { + if (!mixInterpolation) throw new Error("mixInterpolation cannot be null."); + this.mixInterpolation = mixInterpolation; + } + mix() { + if (this.mixDuration === 0) return 1; + let mix = this.mixTime / this.mixDuration; + if (mix >= 1) return 1; + if (this.mixInterpolation === Interpolation.linear) return mix; + mix = this.mixInterpolation.apply(mix); + if (mix < 0) return 0; + if (mix > 1) return 1; + return mix; + } + /** For each timeline: + * - Bits 0-1: MixFrom. + * - Bit 2, HOLD: 0 = mix out using alphaMix, 1 = apply full alpha to prevent dipping. Timeline is first on its track to + * set the property and the next entry (mixingTo) also sets it. When held, timelineHoldMix's mix controls how the hold fades + * out (for 3+ entry chains where the chain eventually stops setting the property). */ + timelineMode = []; + timelineHoldMix = []; + timelinesRotation = []; + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.mixInterpolation = Interpolation.linear; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + /** Uses {@link trackTime} to compute the `animationTime`, which is always between {@link animationStart} and + * {@link animationEnd}. When `trackTime` is 0, `animationTime` is equal to the + * `animationStart` time. */ + getAnimationTime() { + if (!this.loop) return Math.min(this.trackTime + this.animationStart, this.animationEnd); + const duration = this.animationEnd - this.animationStart; + if (duration === 0) return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + /** Returns true if at least one loop has been completed. + * + * See {@link AnimationStateListener.complete}. */ + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + /** When {@link shortestRotation} is false, this clears the directions for mixing this entry's rotation. This can be useful + * to avoid bones rotating the long way around when using {@link getAlpha} and starting animations on other tracks. + * + * Mixing involves finding a rotation between two others. There are two possible solutions: the short or the long way + * around. When the two rotations change over time, which direction is the short or long way can also change. If the short + * way was always chosen, bones flip to the other side when that direction became the long way. TrackEntry chooses the short + * way the first time it is applied and remembers that direction. Resetting that direction makes it choose a new short way + * on the next apply. */ + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + /** If this track entry is non-looping, this is the track time in seconds when {@link animationEnd} is reached, or the + * current {@link trackTime} if it has already been reached. + * + * If this track entry is looping, this is the track time when this animation will reach its next {@link animationEnd} (the + * next loop completion). */ + getTrackComplete() { + const duration = this.animationEnd - this.animationStart; + if (duration !== 0) { + if (this.loop) return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) return duration; + } + return this.trackTime; + } + /** Returns true if this track entry has been applied at least once. + * + * See {@link AnimationState.apply}. */ + wasApplied() { + return this.nextTrackLast !== -1; + } + /** Returns true if there is a {@link next} track entry and it will become the current track entry during the next + * {@link AnimationState.update}. */ + isNextReady() { + return this.next != null && this.nextTrackLast - this.next.delay >= 0; + } + }; + var EventQueue = class { + objects = []; + drainDisabled = false; + animState; + constructor(animState) { + this.animState = animState; + } + start(entry) { + this.objects.push(0 /* start */); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(1 /* interrupt */); + this.objects.push(entry); + } + end(entry) { + this.objects.push(2 /* end */); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(3 /* dispose */); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(4 /* complete */); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(5 /* event */); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) return; + this.drainDisabled = true; + for (let i = 0; i < this.objects.length; i += 2) { + const objects = this.objects; + const type = objects[i]; + const entry = objects[i + 1]; + const listeners = this.animState.listeners.slice(); + switch (type) { + case 0 /* start */: + if (entry.listener?.start) entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.start) listener.start(entry); + } + break; + case 1 /* interrupt */: + if (entry.listener?.interrupt) entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.interrupt) listener.interrupt(entry); + } + break; + // biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime does fall through + case 2 /* end */: + if (entry.listener?.end) entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.end) listener.end(entry); + } + // Fall through. + case 3 /* dispose */: + if (entry.listener?.dispose) entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.dispose) listener.dispose(entry); + } + this.animState.trackEntryPool.free(entry); + break; + case 4 /* complete */: + if (entry.listener?.complete) entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.complete) listener.complete(entry); + } + break; + case 5 /* event */: { + const event = objects[i++ + 2]; + if (entry.listener?.event) entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) { + const listener = listeners[ii]; + if (listener.event) listener.event(entry, event); + } + break; + } + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } + }; + var EventType = /* @__PURE__ */ ((EventType2) => { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + return EventType2; + })(EventType || {}); + var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } + }; + var CURRENT = 0; + var SETUP = 1; + var FIRST = 2; + var MODE = 3; + var HOLD = 4; + var ATTACH_SETUP = 1; + var ATTACH_RETAIN = 2; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + /** The SkeletonData to look up animations when they are specified by name. */ + skeletonData; + animationToMixTime = {}; + /** The mix duration to use when no mix duration has been defined between two animations. */ + defaultMix = 0; + constructor(skeletonData) { + if (!skeletonData) throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + setMix(from, to, duration) { + if (typeof from === "string") + return this.setMix1(from, to, duration); + return this.setMix2(from, to, duration); + } + setMix1(fromName, toName, duration) { + const from = this.skeletonData.findAnimation(fromName); + if (!from) throw new Error(`Animation not found: ${fromName}`); + const to = this.skeletonData.findAnimation(toName); + if (!to) throw new Error(`Animation not found: ${toName}`); + this.setMix2(from, to, duration); + } + setMix2(from, to, duration) { + if (!from) throw new Error("from cannot be null."); + if (!to) throw new Error("to cannot be null."); + const key = `${from.name}.${to.name}`; + this.animationToMixTime[key] = duration; + } + /** Returns the mix duration to use when changing from the specified animation to the other on the same track, or the + * {@link defaultMix} if no mix duration has been set. */ + getMix(from, to) { + const key = `${from.name}.${to.name}`; + const value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } + }; + + // spine-core/src/AssetManagerBase.ts + var AssetManagerBase = class { + constructor(textureLoader, pathPrefix = "", downloader = new Downloader(), cache = new AssetCache()) { + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader; + this.cache = cache; + } + errors = {}; + toLoad = 0; + loaded = 0; + texturePmaInfo = {}; + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.cache.assets[path] = asset; + this.cache.assetsRefCount[path] = (this.cache.assetsRefCount[path] || 0) + 1; + if (callback) callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) callback(path, message); + } + loadAll() { + const promise = new Promise((resolve, reject) => { + const check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) reject(this.errors); + else resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + resolve(data); + }, (status, responseText) => { + const errorMsg = `Couldn't load binary ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + loadText(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + resolve(data); + }, (status, responseText) => { + const errorMsg = `Couldn't load JSON ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + reuseAssets(path, success = () => { + }, error = () => { + }) { + const loadedStatus = this.cache.getAsset(path); + const alreadyExistsOrLoading = loadedStatus !== void 0; + if (alreadyExistsOrLoading) { + this.cache.assetsLoaded[path] = loadedStatus.then((data) => { + data = data instanceof Image || data instanceof ImageBitmap ? this.textureLoader(data) : data; + this.success(success, path, data); + return data; + }).catch((errorMsg) => { + this.error(error, path, errorMsg); + return void 0; + }); + } + return alreadyExistsOrLoading; + } + loadTexture(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + const pma = this.texturePmaInfo[path]; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + const isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + const isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) return response.blob(); + const errorMsg = `Couldn't load image: ${path}`; + this.error(error, path, `Couldn't load image: ${path}`); + reject(errorMsg); + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) { + const texture = this.createTexture(path, pma, bitmap); + this.success(success, path, texture); + resolve(texture); + } + ; + }); + } else { + const image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + const texture = this.createTexture(path, pma, image); + this.success(success, path, texture); + resolve(texture); + }; + image.onerror = () => { + const errorMsg = `Couldn't load image: ${path}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }; + if (this.downloader.rawDataUris[path]) path = this.downloader.rawDataUris[path]; + image.src = path; + } + }); + } + loadTextureAtlas(path, success = () => { + }, error = () => { + }, fileAlias) { + const index = path.lastIndexOf("/"); + const parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadText(path, (atlasText) => { + try { + const atlas = this.createTextureAtlas(atlasText, parent, path, fileAlias); + let toLoad = atlas.pages.length, abort = false; + if (toLoad === 0) { + this.success(success, path, atlas); + resolve(atlas); + return; + } + for (const page of atlas.pages) { + this.loadTexture( + this.texturePath(parent, page.name, fileAlias), + (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad === 0) { + this.success(success, path, atlas); + resolve(atlas); + } + } + }, + (imagePath, message) => { + if (!abort) { + const errorMsg = `Couldn't load texture ${path} page image: ${imagePath}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + abort = true; + } + ); + } + } catch (e) { + const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + }, (status, responseText) => { + const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + loadTextureAtlasButNoTextures(path, success = () => { + }, error = () => { + }) { + const index = path.lastIndexOf("/"); + const parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + if (this.reuseAssets(path, success, error)) return; + this.cache.assetsLoaded[path] = new Promise((resolve, reject) => { + this.downloader.downloadText(path, (atlasText) => { + try { + const atlas = this.createTextureAtlas(atlasText, parent, path); + this.success(success, path, atlas); + resolve(atlas); + } catch (e) { + const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; + this.error(error, path, errorMsg); + reject(errorMsg); + } + }, (status, responseText) => { + const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; + this.error(error, path, errorMsg); + reject(errorMsg); + }); + }); + } + async loadBinaryAsync(path) { + return new Promise((resolve, reject) => { + this.loadBinary( + path, + (_, binary) => resolve(binary), + (_, message) => reject(message) + ); + }); + } + async loadJsonAsync(path) { + return new Promise((resolve, reject) => { + this.loadJson( + path, + (_, object) => resolve(object), + (_, message) => reject(message) + ); + }); + } + async loadTextureAsync(path) { + return new Promise((resolve, reject) => { + this.loadTexture( + path, + (_, texture) => resolve(texture), + (_, message) => reject(message) + ); + }); + } + async loadTextureAtlasAsync(path) { + return new Promise((resolve, reject) => { + this.loadTextureAtlas( + path, + (_, atlas) => resolve(atlas), + (_, message) => reject(message) + ); + }); + } + async loadTextureAtlasButNoTexturesAsync(path) { + return new Promise((resolve, reject) => { + this.loadTextureAtlasButNoTextures( + path, + (_, atlas) => resolve(atlas), + (_, message) => reject(message) + ); + }); + } + setCache(cache) { + this.cache = cache; + } + get(path) { + return this.cache.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + const asset = this.cache.assets[path]; + if (asset) return asset; + const error = this.errors[path]; + throw Error(`Asset not found: ${path}${error ? ` +${error}` : ""}`); + } + remove(path) { + path = this.pathPrefix + path; + const asset = this.cache.assets[path]; + if (asset.dispose) asset.dispose(); + delete this.cache.assets[path]; + delete this.cache.assetsRefCount[path]; + delete this.cache.assetsLoaded[path]; + return asset; + } + removeAll() { + for (const path in this.cache.assets) { + const asset = this.cache.assets[path]; + if (asset.dispose) asset.dispose(); + } + this.cache.assets = {}; + this.cache.assetsLoaded = {}; + this.cache.assetsRefCount = {}; + } + isLoadingComplete() { + return this.toLoad === 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + // dispose asset only if it's not used by others + disposeAsset(path) { + const asset = this.cache.assets[path]; + if (asset instanceof TextureAtlas) { + asset.dispose(); + return; + } + this.disposeAssetInternal(path); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } + disposeAssetInternal(path) { + if (this.cache.assetsRefCount[path] > 0 && --this.cache.assetsRefCount[path] === 0) { + return this.remove(path); + } + } + createTextureAtlas(atlasText, parentPath, path, fileAlias) { + const atlas = new TextureAtlas(atlasText); + atlas.dispose = () => { + if (this.cache.assetsRefCount[path] <= 0) return; + this.disposeAssetInternal(path); + for (const page of atlas.pages) { + page.texture?.dispose(); + } + }; + for (const page of atlas.pages) { + const texturePath = this.texturePath(parentPath, page.name, fileAlias); + this.texturePmaInfo[this.pathPrefix + texturePath] = page.pma; + } + return atlas; + } + createTexture(path, pma, image) { + const texture = this.textureLoader(image, pma); + const textureDispose = texture.dispose.bind(texture); + texture.dispose = () => { + if (this.disposeAssetInternal(path)) textureDispose(); + }; + return texture; + } + texturePath(parentPath, pageName, fileAlias) { + if (!fileAlias) return parentPath + pageName; + return fileAlias[pageName]; + } + }; + var AssetCache = class _AssetCache { + assets = {}; + assetsRefCount = {}; + assetsLoaded = {}; + static AVAILABLE_CACHES = /* @__PURE__ */ new Map(); + static getCache(id) { + const cache = _AssetCache.AVAILABLE_CACHES.get(id); + if (cache) return cache; + const newCache = new _AssetCache(); + _AssetCache.AVAILABLE_CACHES.set(id, newCache); + return newCache; + } + async addAsset(path, asset) { + this.assetsLoaded[path] = Promise.resolve(asset); + this.assets[path] = asset; + return asset; + } + getAsset(path) { + return this.assetsLoaded[path]; + } + }; + var Downloader = class { + callbacks = {}; + rawDataUris = {}; + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx !== -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx === -1) throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) return; + const rawDataUri = this.rawDataUris[url]; + if (rawDataUri && !rawDataUri.includes(".")) { + try { + this.finish(url, 200, this.dataUriToString(rawDataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + const request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", rawDataUri ? rawDataUri : url, true); + const done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) return; + const rawDataUri = this.rawDataUris[url]; + if (rawDataUri && !rawDataUri.includes(".")) { + try { + this.finish(url, 200, this.dataUriToUint8Array(rawDataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + const request = new XMLHttpRequest(); + request.open("GET", rawDataUri ? rawDataUri : url, true); + request.responseType = "arraybuffer"; + const onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status === 200 || request.status === 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + const callbacks = this.callbacks[url]; + delete this.callbacks[url]; + if (status === 200 || status === 0) { + for (let i = 0, n = callbacks.length; i < n; i += 2) + callbacks[i](data); + } else { + for (let i = 1, n = callbacks.length; i < n; i += 2) + callbacks[i](status, data); + } + } + }; + + // spine-core/src/attachments/BoundingBoxAttachment.ts + var BoundingBoxAttachment = class _BoundingBoxAttachment extends VertexAttachment { + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + const copy = new _BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/ClippingAttachment.ts + var ClippingAttachment = class _ClippingAttachment extends VertexAttachment { + /** Clipping is performed between the clipping attachment's slot and the end slot. If null, clipping is done until the end of + * the skeleton's rendering. */ + endSlot = null; + /** When true the clipping polygon is treated as convex for more efficient clipping. If the polygon deforms to concave then the + * convex hull is used. When false the clipping polygon can be concave and if so has an additional CPU cost. Inverse clipping + * always uses convex. */ + convex = false; + /** When false, everything inside the clipping polygon is visible. When true, everything outside the clipping polygon is + * visible and clipping is convex. */ + inverse = false; + // Nonessential. + /** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons + * are not usually rendered at runtime. */ + color = new Color(0.2275, 0.2275, 0.8078, 1); + // ce3a3aff + constructor(name) { + super(name); + } + copy() { + const copy = new _ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.convex = this.convex; + copy.inverse = this.inverse; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PathAttachment.ts + var PathAttachment = class _PathAttachment extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ + lengths = []; + /** If true, the start and end knots are connected. */ + closed = false; + /** If true, additional calculations are performed to make computing positions along the path more accurate so movement along + * the path has a constant speed. */ + constantSpeed = false; + /** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually + * rendered at runtime. */ + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + const copy = new _PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = []; + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = this.closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PointAttachment.ts + var PointAttachment = class _PointAttachment extends VertexAttachment { + /** The local x position. */ + x = 0; + /** The local y position. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments + * are not usually rendered at runtime. */ + color = new Color(0.38, 0.94, 0, 1); + constructor(name) { + super(name); + } + /** Computes the world position from the local position. */ + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + /** Computes the world rotation from the local rotation. */ + computeWorldRotation(bone) { + const r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const x = cos * bone.a + sin * bone.b; + const y = cos * bone.c + sin * bone.d; + return MathUtils.atan2Deg(y, x); + } + copy() { + const copy = new _PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/AtlasAttachmentLoader.ts + var AtlasAttachmentLoader = class { + atlas; + allowMissingRegions; + constructor(atlas, allowMissingRegions = false) { + this.atlas = atlas; + this.allowMissingRegions = allowMissingRegions; + } + /** Sets each {@link Sequence.regions} by calling {@link findRegion} for each texture region using + * {@link Sequence.getPath}. */ + findRegions(name, basePath, sequence) { + const regions = sequence.regions; + for (let i = 0, n = regions.length; i < n; i++) + regions[i] = this.findRegion(name, sequence.getPath(basePath, i)); + } + /** Looks for the region with the specified path. If not found and {@link allowMissingRegions} is false, an error is + * raised. */ + findRegion(name, path) { + const region = this.atlas.findRegion(path); + if (!region && !this.allowMissingRegions) + throw new Error(`Region not found in atlas: ${path} (attachment: ${name})`); + return region; + } + newRegionAttachment(skin, placeholder, name, path, sequence) { + this.findRegions(name, path, sequence); + return new RegionAttachment(name, sequence); + } + newMeshAttachment(skin, placeholder, name, path, sequence) { + this.findRegions(name, path, sequence); + return new MeshAttachment(name, sequence); + } + newBoundingBoxAttachment(skin, placeholder, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, placeholder, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, placeholder, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, placeholder, name) { + return new ClippingAttachment(name); + } + }; + + // spine-core/src/PosedData.ts + var PosedData = class { + name; + setupPose; + /** When true, {@link Skeleton.updateWorldTransform} only updates this constraint if the {@link Skeleton.skin} + * contains this constraint. + * + * See {@link Skin.constraints}. */ + skinRequired = false; + constructor(name, setupPose) { + if (name == null) throw new Error("name cannot be null."); + this.name = name; + this.setupPose = setupPose; + } + }; + + // spine-core/src/BoneData.ts + var BoneData = class _BoneData extends PosedData { + /** The index of the bone in {@link Skeleton.bones}. */ + index = 0; + /** The parent bone, or null if this bone is the root. */ + parent = null; + /** The bone's length. */ + length = 0; + // Nonessential. + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually + * rendered at runtime. */ + color = new Color(); + /** The bone icon name as it was in Spine, or null if nonessential data was not exported. */ + icon; + /** The bone icon's display size scale, or 1 if nonessential data was not exported. */ + iconSize = 1; + /** The bone icon's display rotation in degrees, or 0 if nonessential data was not exported. */ + iconRotation = 0; + /** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = false; + constructor(index, name, parent) { + super(name, new BonePose()); + if (index < 0) throw new Error("index must be >= 0."); + if (!name) throw new Error("name cannot be null."); + this.index = index; + this.parent = parent; + } + copy(parent) { + const copy = new _BoneData(this.index, this.name, parent); + copy.length = this.length; + copy.setupPose.set(this.setupPose); + return copy; + } + }; + var Inherit = /* @__PURE__ */ ((Inherit2) => { + Inherit2[Inherit2["Normal"] = 0] = "Normal"; + Inherit2[Inherit2["OnlyTranslation"] = 1] = "OnlyTranslation"; + Inherit2[Inherit2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + Inherit2[Inherit2["NoScale"] = 3] = "NoScale"; + Inherit2[Inherit2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + return Inherit2; + })(Inherit || {}); + + // spine-core/src/BonePose.ts + var BonePose = class { + bone; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 0; + /** The local scaleY. */ + scaleY = 0; + /** The local shearX. */ + shearX = 0; + /** The local shearY. */ + shearY = 0; + inherit = 0 /* Normal */; + /** The world transform `[a b][c d]` x-axis x component. */ + a = 0; + /** The world transform `[a b][c d]` y-axis x component. */ + b = 0; + /** The world transform `[a b][c d]` x-axis y component. */ + c = 0; + /** The world transform `[a b][c d]` y-axis y component. */ + d = 0; + /** The world X position. If changed, {@link updateLocalTransform} should be called. */ + worldY = 0; + /** The world Y position. If changed, {@link updateLocalTransform} should be called. */ + worldX = 0; + world = 0; + local = 0; + set(pose) { + if (pose == null) throw new Error("pose cannot be null."); + this.x = pose.x; + this.y = pose.y; + this.rotation = pose.rotation; + this.scaleX = pose.scaleX; + this.scaleY = pose.scaleY; + this.shearX = pose.shearX; + this.shearY = pose.shearY; + this.inherit = pose.inherit; + } + setPosition(x, y) { + this.x = x; + this.y = y; + } + setScale(scaleOrX, scaleY) { + this.scaleX = scaleOrX; + this.scaleY = scaleY === void 0 ? scaleOrX : scaleY; + } + /** Determines how parent world transforms affect this bone. */ + getInherit() { + return this.inherit; + } + setInherit(inherit) { + if (inherit == null) throw new Error("inherit cannot be null."); + this.inherit = inherit; + } + /** Called by {@link Skeleton.updateCache} to compute the world transform, if needed. */ + update(skeleton, physics) { + if (this.world !== skeleton._update) this.updateWorldTransform(skeleton); + } + /** Computes the world transform using the parent bone's world transform and this applied local pose. Child bones are not + * updated. + * + * See World transforms in the Spine + * Runtimes Guide. */ + updateWorldTransform(skeleton) { + if (this.local === skeleton._update) + this.updateLocalTransform(skeleton); + else + this.world = skeleton._update; + const rotation = this.rotation; + const scaleX = this.scaleX; + const scaleY = this.scaleY; + const shearX = this.shearX; + const shearY = this.shearY; + if (!this.bone.parent) { + const sx = skeleton.scaleX, sy = skeleton.scaleY; + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX * sx; + this.b = Math.cos(ry) * scaleY * sx; + this.c = Math.sin(rx) * scaleX * sy; + this.d = Math.sin(ry) * scaleY * sy; + this.worldX = this.x * sx + skeleton.x; + this.worldY = this.y * sy + skeleton.y; + return; + } + const parent = this.bone.parent.appliedPose; + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * this.x + pb * this.y + parent.worldX; + this.worldY = pc * this.x + pd * this.y + parent.worldY; + switch (this.inherit) { + case 0 /* Normal */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case 1 /* OnlyTranslation */: { + const sx = skeleton.scaleX, sy = skeleton.scaleY; + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX * sx; + this.b = Math.cos(ry) * scaleY * sx; + this.c = Math.sin(rx) * scaleX * sy; + this.d = Math.sin(ry) * scaleY * sy; + break; + } + case 2 /* NoRotationOrReflection */: { + const sx = skeleton.scaleX, sy = skeleton.scaleY, sxi = 1 / sx, syi = 1 / sy; + pa *= sxi; + pc *= syi; + let s = pa * pa + pc * pc; + let r = 0; + if (s > MathUtils.epsilon2) { + s = Math.abs(pa * pd * syi - pb * sxi * pc) / s; + pb = pc * s; + pd = pa * s; + r = rotation - MathUtils.atan2Deg(pc, pa); + } else { + pa = 0; + pc = 0; + r = rotation - 90 + MathUtils.atan2Deg(pd, pb); + } + const rx = (r + shearX) * MathUtils.degRad; + const ry = (r + shearY + 90) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = (pa * la - pb * lc) * sx; + this.b = (pa * lb - pb * ld) * sx; + this.c = (pc * la + pd * lc) * sy; + this.d = (pc * lb + pd * ld) * sy; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + const sx = skeleton.scaleX, sy = skeleton.scaleY, sxi = 1 / sx, syi = 1 / sy; + const r = rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + let za = (pa * cos + pb * sin) * sxi; + let zc = (pc * cos + pd * sin) * syi; + const s = 1 / Math.sqrt(za * za + zc * zc); + za *= s; + zc *= s; + let zb = -zc, zd = za; + if (this.inherit === 3 /* NoScale */ && pa * pd - pb * pc < 0 !== (sx < 0 !== sy < 0)) { + zb = -zb; + zd = -zd; + } + const rx = shearX * MathUtils.degRad; + const ry = (90 + shearY) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = (za * la + zb * lc) * sx; + this.b = (za * lb + zb * ld) * sx; + this.c = (zc * la + zd * lc) * sy; + this.d = (zc * lb + zd * ld) * sy; + break; + } + } + } + /** Computes the local transform values from the world transform. + * + * If the world transform is modified (by a constraint, {@link rotateWorld}, etc) then this method should be called so + * the local transform matches the world transform. The local transform may be needed by other code (eg to apply another + * constraint). + * + * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after + * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ + updateLocalTransform(skeleton) { + this.local = 0; + this.world = skeleton._update; + const sx = skeleton.scaleX, sy = skeleton.scaleY; + if (!this.bone.parent) { + const sxi = 1 / sx, syi = 1 / sy; + this.x = (this.worldX - skeleton.x) * sxi; + this.y = (this.worldY - skeleton.y) * syi; + this.set5(this.a * sxi, this.b * sxi, this.c * syi, this.d * syi, 0); + return; + } + const parent = this.bone.parent.appliedPose; + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + const pad = pa * pd - pb * pc, pid = 1 / (pa * pd - pb * pc); + const ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + const dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.x = dx * ia - dy * ib; + this.y = dy * id - dx * ic; + switch (this.inherit) { + case 0 /* Normal */: + this.set5(ia * this.a - ib * this.c, ia * this.b - ib * this.d, id * this.c - ic * this.a, id * this.d - ic * this.b, 0); + break; + case 1 /* OnlyTranslation */: { + const sxi = 1 / sx, syi = 1 / sy; + this.set5(this.a * sxi, this.b * sxi, this.c * syi, this.d * syi, 0); + break; + } + case 2 /* NoRotationOrReflection */: { + const sxi = 1 / sx, syi = 1 / sy; + pa *= sxi; + pc *= syi; + const wa = this.a * sxi, wb = this.b * sxi, wc = this.c * syi, wd = this.d * syi; + const s = 1 / (pa * pa + pc * pc), det = 1 / Math.abs(pad * sxi * syi); + this.set5( + (pa * wa + pc * wc) * s, + (pa * wb + pc * wd) * s, + (pa * wc - pc * wa) * det, + (pa * wd - pc * wb) * det, + MathUtils.atan2Deg(pc, pa) + ); + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + const sxi = 1 / sx, syi = 1 / sy; + const wa = this.a * sxi, wb = this.b * sxi, wc = this.c * syi, wd = this.d * syi; + let tx = pd * this.a - pb * this.c, ty = pa * this.c - pc * this.a; + if (pad < 0) { + tx = -tx; + ty = -ty; + } + let r = MathUtils.atan2Deg(ty, tx); + this.rotation = r; + r *= MathUtils.degRad; + const cos = Math.cos(r), sin = Math.sin(r); + let za = (pa * cos + pb * sin) * sxi; + let zc = (pc * cos + pd * sin) * syi; + const s = 1 / Math.sqrt(za * za + zc * zc); + za *= s; + zc *= s; + const si = this.inherit === 3 /* NoScale */ && pad < 0 !== (sx < 0 !== sy < 0) ? -1 : 1; + this.set4(za * wa + zc * wc, za * wb + zc * wd, (za * wc - zc * wa) * si, (za * wd - zc * wb) * si); + } + } + } + set4(ra, rb, rc, rd) { + const x = ra * ra + rc * rc, y = rb * rb + rd * rd; + if (x > MathUtils.epsilon2) { + this.shearX = MathUtils.atan2Deg(rc, ra); + this.scaleX = Math.sqrt(x); + } else { + this.shearX = 0; + this.scaleX = 0; + } + this.scaleY = Math.sqrt(y); + if (y > MathUtils.epsilon2) { + this.shearY = MathUtils.atan2Deg(rd, rb); + if (ra * rd - rb * rc < 0) { + this.scaleY = -this.scaleY; + this.shearY += 90; + } else + this.shearY -= 90; + if (this.shearY > 180) + this.shearY -= 360; + else if (this.shearY <= -180) + this.shearY += 360; + } else + this.shearY = 0; + } + set5(ra, rb, rc, rd, ro) { + this.shearX = 0; + const x = ra * ra + rc * rc, y = rb * rb + rd * rd; + if (x > MathUtils.epsilon2) { + const r = MathUtils.atan2Deg(rc, ra); + this.rotation = r + ro; + this.scaleX = Math.sqrt(x); + this.scaleY = Math.sqrt(y); + if (y > MathUtils.epsilon2) { + this.shearY = MathUtils.atan2Deg(rd, rb); + if (ra * rd - rb * rc < 0) { + this.scaleY = -this.scaleY; + this.shearY += 90 - r; + } else + this.shearY -= 90 + r; + if (this.shearY > 180) + this.shearY -= 360; + else if (this.shearY <= -180) + this.shearY += 360; + } else + this.shearY = 0; + } else { + this.scaleX = 0; + this.scaleY = Math.sqrt(y); + this.shearY = 0; + this.rotation = y > MathUtils.epsilon2 ? MathUtils.atan2Deg(rd, rb) - 90 + ro : ro; + } + } + /** If the world transform has been modified by constraints and the local transform no longer matches, + * {@link updateLocalTransform} is called. Call this after {@link Skeleton.updateWorldTransform} before + * using the applied local transform. */ + validateLocalTransform(skeleton) { + if (this.local === skeleton._update) this.updateLocalTransform(skeleton); + } + modifyLocal(skeleton) { + if (this.local === skeleton._update) this.updateLocalTransform(skeleton); + this.world = 0; + this.resetWorld(skeleton, skeleton._update); + } + modifyWorld(skeleton) { + const update = skeleton._update; + this.local = update; + this.world = update; + this.resetWorld(skeleton, update); + } + resetWorld(skeleton, update) { + const children = this.bone.children; + for (let i = 0, n = children.length; i < n; i++) { + const child = children[i].appliedPose; + if (child.world === update) { + if (child.local === update) child.updateLocalTransform(skeleton); + child.world = 0; + child.resetWorld(skeleton, update); + } + } + } + /** The world rotation for the X axis, calculated using {@link a} and {@link c}. This is the direction the bone is + * pointing. */ + getWorldRotationX() { + return MathUtils.atan2Deg(this.c, this.a); + } + /** The world rotation for the Y axis, calculated using {@link b} and {@link d}. */ + getWorldRotationY() { + return MathUtils.atan2Deg(this.d, this.b); + } + /** The magnitude (always positive) of the world scale X, calculated using {@link a} and {@link c}. */ + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + /** The magnitude (always positive) of the world scale Y, calculated using {@link b} and {@link d}. */ + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + // public Matrix3 getWorldTransform (Matrix3 worldTransform) { + // if (worldTransform == null) throw new IllegalArgumentException("worldTransform cannot be null."); + // float[] val = worldTransform.val; + // val[M00] = a; + // val[M01] = b; + // val[M10] = c; + // val[M11] = d; + // val[M02] = worldX; + // val[M12] = worldY; + // val[M20] = 0; + // val[M21] = 0; + // val[M22] = 1; + // return worldTransform; + // } + /** Transforms a point from world coordinates to the bone's local coordinates. */ + worldToLocal(world) { + if (world == null) throw new Error("world cannot be null."); + const det = this.a * this.d - this.b * this.c; + const x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * this.d - y * this.b) / det; + world.y = (y * this.a - x * this.c) / det; + return world; + } + /** Transforms a point from the bone's local coordinates to world coordinates. */ + localToWorld(local) { + if (local == null) throw new Error("local cannot be null."); + const x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + worldToParent(world) { + if (world == null) throw new Error("world cannot be null."); + return this.bone.parent == null ? world : this.bone.parent.appliedPose.worldToLocal(world); + } + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + parentToWorld(world) { + if (world == null) throw new Error("world cannot be null."); + return this.bone.parent == null ? world : this.bone.parent.appliedPose.localToWorld(world); + } + /** Transforms a world rotation to a local rotation. */ + worldToLocalRotation(worldRotation) { + worldRotation *= MathUtils.degRad; + const sin = Math.sin(worldRotation), cos = Math.cos(worldRotation); + return MathUtils.atan2Deg(this.a * sin - this.c * cos, this.d * cos - this.b * sin) + this.rotation - this.shearX; + } + /** Transforms a local rotation to a world rotation. */ + localToWorldRotation(localRotation) { + localRotation = (localRotation - this.rotation - this.shearX) * MathUtils.degRad; + const sin = Math.sin(localRotation), cos = Math.cos(localRotation); + return MathUtils.atan2Deg(cos * this.c + sin * this.d, cos * this.a + sin * this.b); + } + /** Rotates the world transform the specified amount. */ + rotateWorld(degrees) { + degrees *= MathUtils.degRad; + const sin = Math.sin(degrees), cos = Math.cos(degrees); + const ra = this.a, rb = this.b; + this.a = cos * ra - sin * this.c; + this.b = cos * rb - sin * this.d; + this.c = sin * ra + cos * this.c; + this.d = sin * rb + cos * this.d; + } + }; + + // spine-core/src/Posed.ts + var Posed = class { + /** The constraint's setup pose data. */ + data; + pose; + constrainedPose; + appliedPose; + constructor(data, pose, constrainedPose) { + if (data == null) throw new Error("data cannot be null."); + this.data = data; + this.pose = pose; + this.constrainedPose = constrainedPose; + this.appliedPose = pose; + } + /** Sets the unconstrained pose to the setup pose. */ + setupPose() { + this.pose.set(this.data.setupPose); + } + /** The setup pose data. May be shared with multiple instances. */ + getData() { + return this.data; + } + /** The unconstrained pose for this object, set by animations and application code. */ + getPose() { + return this.pose; + } + /** The pose to use for rendering. If no constraints modify this pose, this is the same as {@link pose}. Otherwise it is a + * copy of {@link pose} modified by constraints. */ + getAppliedPose() { + return this.appliedPose; + } + /** Sets the applied pose to the unconstrained pose, for when no constraints will modify the pose. */ + unconstrained() { + this.appliedPose = this.pose; + } + /** Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints. */ + constrained() { + this.appliedPose = this.constrainedPose; + } + /** Sets the constrained pose to the unconstrained pose, as a starting point for constraints to be applied. */ + resetConstrained() { + this.constrainedPose.set(this.pose); + } + }; + + // spine-core/src/PosedActive.ts + var PosedActive = class extends Posed { + active = false; + constructor(data, pose, constrained) { + super(data, pose, constrained); + this.setupPose(); + } + /** Returns false when this constraint won't be updated by + * {@link Skeleton.updateWorldTransform} because a skin is required and the + * {@link Skeleton.skin active skin} does not contain this item. See {@link Skin.bones}, {@link Skin.constraints}, + * {@link PosedData.skinRequired}, and {@link Skeleton.updateCache}. */ + isActive() { + return this.active; + } + }; + + // spine-core/src/Bone.ts + var Bone = class _Bone extends PosedActive { + /** The parent bone, or null if this is the root bone. */ + parent = null; + /** The immediate children of this bone. */ + children = []; + sorted = false; + constructor(data, parent) { + super(data, new BonePose(), new BonePose()); + this.parent = parent; + this.appliedPose.bone = this; + this.constrainedPose.bone = this; + } + /** Copy constructor. Does not copy the {@link children} bones. */ + copy(parent) { + const copy = new _Bone(this.data, parent); + copy.pose.set(this.pose); + return copy; + } + }; + + // spine-core/src/Constraint.ts + var Constraint = class extends PosedActive { + constructor(data, pose, constrained) { + super(data, pose, constrained); + } + isSourceActive() { + return true; + } + }; + + // spine-core/src/DrawOrder.ts + var DrawOrder = class { + _setupPose; + /** The unconstrained draw order, set by animations and application code. */ + pose; + constrainedPose; + /** The constrained draw order for rendering. If no constraints modify the draw order, this is the same as {@link pose}. + * Otherwise it is a copy of {@link pose} modified by constraints. */ + appliedPose; + constructor(setupPose) { + this._setupPose = setupPose; + this.pose = [...setupPose]; + this.constrainedPose = []; + this.appliedPose = this.pose; + } + /** Sets the unconstrained draw order to the setup pose order. */ + setupPose() { + this.pose.length = this._setupPose.length; + Utils.arrayCopy(this._setupPose, 0, this.pose, 0, this._setupPose.length); + } + /** Sets the applied pose to the unconstrained pose, for when no constraints will modify the draw order. */ + unconstrained() { + this.appliedPose = this.pose; + } + /** Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints. */ + constrained() { + this.appliedPose = this.constrainedPose; + } + /** Copies the unconstrained pose to the constrained pose, as a starting point for constraints to be applied. */ + resetConstrained() { + this.constrainedPose.length = this.pose.length; + Utils.arrayCopy(this.pose, 0, this.constrainedPose, 0, this.pose.length); + } + }; + + // spine-core/src/ConstraintData.ts + var ConstraintData = class extends PosedData { + constructor(name, setup) { + super(name, setup); + } + }; + var ScaleYMode = /* @__PURE__ */ ((ScaleYMode2) => { + ScaleYMode2[ScaleYMode2["None"] = 0] = "None"; + ScaleYMode2[ScaleYMode2["Uniform"] = 1] = "Uniform"; + ScaleYMode2[ScaleYMode2["Volume"] = 2] = "Volume"; + return ScaleYMode2; + })(ScaleYMode || {}); + + // spine-core/src/Event.ts + var Event = class { + /** The animation time this event was keyed, or -1 for the setup pose. */ + time = 0; + data; + /** The integer payload for this event. */ + intValue = 0; + /** The float payload for this event. */ + floatValue = 0; + stringValue = null; + /** If an audio path is set, the volume for the audio. */ + volume = 0; + /** If an audio path is set, the left/right balance for the audio. */ + balance = 0; + constructor(time, data) { + if (!data) throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + }; + + // spine-core/src/EventData.ts + var EventData = class { + /** The name of the event, unique across all events in the skeleton. + * + * See {@link SkeletonData.findEvent}. */ + name; + _audioPath = null; + /** Path to an audio file relative to the audio folder as defined in Spine. */ + get audioPath() { + return this._audioPath; + } + set audioPath(audioPath) { + if (audioPath == null) throw new Error("audioPath cannot be null."); + this._audioPath = audioPath; + } + /** The setup values that are shared by all events with this data. */ + setupPose = new Event(-1, this); + constructor(name) { + this.name = name; + } + }; + + // spine-core/src/IkConstraintPose.ts + var IkConstraintPose = class { + /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true and the target is out of range, the parent bone is scaled to reach it. + * + * For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link softness} is > 0, + * and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. + * + * For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */ + mix = 0; + /** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones + * will not straighten completely until the target is this far out of range. */ + softness = 0; + set(pose) { + this.mix = pose.mix; + this.softness = pose.softness; + this.bendDirection = pose.bendDirection; + this.compress = pose.compress; + this.stretch = pose.stretch; + } + }; + + // spine-core/src/IkConstraint.ts + var IkConstraint = class _IkConstraint extends Constraint { + /** The 1 or 2 bones that will be modified by this IK constraint. */ + bones; + /** The bone that is the IK target. */ + target; + constructor(data, skeleton) { + super(data, new IkConstraintPose(), new IkConstraintPose()); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.bones = []; + for (const boneData of data.bones) + this.bones.push(skeleton.bones[boneData.index].constrainedPose); + this.target = skeleton.bones[data.target.index]; + } + copy(skeleton) { + var copy = new _IkConstraint(this.data, skeleton); + copy.pose.set(this.pose); + return copy; + } + update(skeleton, physics) { + const p = this.appliedPose; + if (p.mix === 0) return; + const target = this.target.appliedPose; + const bones = this.bones; + switch (bones.length) { + case 1: + _IkConstraint.apply(skeleton, bones[0], target.worldX, target.worldY, p.compress, p.stretch, this.data.scaleYMode, p.mix); + break; + case 2: + _IkConstraint.apply( + skeleton, + bones[0], + bones[1], + target.worldX, + target.worldY, + p.bendDirection, + p.stretch, + this.data.scaleYMode, + p.softness, + p.mix + ); + break; + } + } + sort(skeleton) { + skeleton.sortBone(this.target); + const parent = this.bones[0].bone; + skeleton.sortBone(parent); + skeleton._updateCache.push(this); + parent.sorted = false; + skeleton.sortReset(parent.children); + skeleton.constrained(parent); + if (this.bones.length > 1) skeleton.constrained(this.bones[1].bone); + } + isSourceActive() { + return this.target.active; + } + static apply(skeleton, boneOrParent, targetXorChild, targetYOrTargetX, compressOrTargetY, stretchOrBendDir, scaleYModeOrStretch, mixOrScaleYMode, softness, mix) { + if (typeof targetXorChild === "number") + _IkConstraint.apply1(skeleton, boneOrParent, targetXorChild, targetYOrTargetX, compressOrTargetY, stretchOrBendDir, scaleYModeOrStretch, mixOrScaleYMode); + else + _IkConstraint.apply2( + skeleton, + boneOrParent, + targetXorChild, + targetYOrTargetX, + compressOrTargetY, + stretchOrBendDir, + scaleYModeOrStretch, + mixOrScaleYMode, + softness, + mix + ); + } + static apply1(skeleton, bone, targetX, targetY, compress, stretch, scaleYMode, mix) { + bone.modifyLocal(skeleton); + const p = bone.bone.parent.appliedPose; + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.shearX - bone.rotation, tx = 0, ty = 0; + switch (bone.inherit) { + case 1 /* OnlyTranslation */: + tx = (targetX - bone.worldX) * MathUtils.signum(skeleton.scaleX); + ty = (targetY - bone.worldY) * MathUtils.signum(skeleton.scaleY); + break; + // biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime + case 2 /* NoRotationOrReflection */: { + const s = Math.abs(pa * pd - pb * pc) / Math.max(MathUtils.epsilon, pa * pa + pc * pc); + const sa = pa / skeleton.scaleX; + const sc = pc / skeleton.scaleY; + pb = -sc * s * skeleton.scaleX; + pd = sa * s * skeleton.scaleY; + rotationIK += MathUtils.atan2Deg(sc, sa); + } + // Fall through + default: { + const x = targetX - p.worldX, y = targetY - p.worldY; + const d = pa * pd - pb * pc; + if (Math.abs(d) <= MathUtils.epsilon) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone.x; + ty = (y * pa - x * pc) / d - bone.y; + } + } + } + rotationIK += MathUtils.atan2Deg(ty, tx); + if (bone.scaleX < 0) rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK <= -180) + rotationIK += 360; + bone.rotation += rotationIK * mix; + if (compress || stretch) { + switch (bone.inherit) { + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + const b = bone.bone.data.length * bone.scaleX; + if (b > MathUtils.epsilon) { + const dd = tx * tx + ty * ty; + if (compress && dd < b * b || stretch && dd > b * b) { + const s = (Math.sqrt(dd) / b - 1) * mix + 1; + bone.scaleX *= s; + switch (scaleYMode) { + case 1 /* Uniform */: + bone.scaleY *= s; + break; + case 2 /* Volume */: + bone.scaleY /= s < 0.7 ? 0.25 + 0.642857 * s : s; + } + } + } + } + } + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ + static apply2(skeleton, parent, child, targetX, targetY, bendDir, stretch, scaleYMode, softness, mix) { + if (parent.inherit !== 0 /* Normal */ || child.inherit !== 0 /* Normal */) return; + parent.modifyLocal(skeleton); + child.modifyLocal(skeleton); + let px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + const u = Math.abs(psx - psy) <= MathUtils.epsilon; + if (!u || stretch) { + child.y = 0; + cwx = a * child.x + parent.worldX; + cwy = c * child.x + parent.worldY; + } else { + cwx = a * child.x + b * child.y + parent.worldX; + cwy = c * child.x + d * child.y + parent.worldY; + } + const pp = parent.bone.parent.appliedPose; + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; + id = Math.abs(id) <= MathUtils.epsilon ? 0 : 1 / id; + const dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.bone.data.length * csx, a1, a2; + if (l1 < MathUtils.epsilon) { + _IkConstraint.apply(skeleton, parent, targetX, targetY, false, stretch, 0 /* None */, mix); + child.rotation = 0; + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness !== 0) { + softness *= psx * (csx + 1) * 0.5; + const td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * mix + 1; + parent.scaleX *= a; + switch (scaleYMode) { + case 1 /* Uniform */: + parent.scaleY *= a; + break; + case 2 /* Volume */: + parent.scaleY /= a < 0.7 ? 0.25 + 0.642857 * a : a; + } + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + const aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + const c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + const r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = Math.sqrt(r0) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + const os = Math.atan2(child.y, child.x) * s2; + a1 = (a1 - os) * MathUtils.radDeg + os1 - parent.rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 <= -180) + a1 += 360; + parent.rotation += a1 * mix; + a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - child.rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 <= -180) + a2 += 360; + child.rotation += a2 * mix; + } + }; + + // spine-core/src/IkConstraintData.ts + var IkConstraintData = class extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ + bones = []; + _target = null; + /** The bone that is the IK target. */ + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) throw new Error("target cannot be null."); + return this._target; + } + /** Determines how the {@link BonePose.scaleY} changes when {@link IkConstraintPose.compress} or + * {@link IkConstraintPose.stretch} set {@link BonePose.scaleX}. */ + _scaleYMode = 0 /* None */; + set scaleYMode(scaleYMode) { + this._scaleYMode = scaleYMode; + } + get scaleYMode() { + if (this._scaleYMode == null) throw new Error("scaleYMode cannot be null."); + return this._scaleYMode; + } + constructor(name) { + super(name, new IkConstraintPose()); + } + create(skeleton) { + return new IkConstraint(this, skeleton); + } + }; + + // spine-core/src/PathConstraintPose.ts + var PathConstraintPose = class { + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ + mixRotate = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ + mixX = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ + mixY = 0; + set(pose) { + this.position = pose.position; + this.spacing = pose.spacing; + this.mixRotate = pose.mixRotate; + this.mixX = pose.mixX; + this.mixY = pose.mixY; + } + }; + + // spine-core/src/PathConstraintData.ts + var PathConstraintData = class extends ConstraintData { + /** The bones that will be modified by this path constraint. */ + bones = []; + /** The slot whose path attachment will be used to constrained the bones. */ + set slot(slotData) { + this._slot = slotData; + } + get slot() { + if (!this._slot) throw new Error("SlotData not set."); + else return this._slot; + } + _slot = null; + /** The mode for positioning the first bone on the path. */ + positionMode = 0 /* Fixed */; + /** The mode for positioning the bones after the first bone on the path. */ + spacingMode = 1 /* Fixed */; + /** The mode for adjusting the rotation of the bones. */ + rotateMode = 1 /* Chain */; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + constructor(name) { + super(name, new PathConstraintPose()); + } + create(skeleton) { + return new PathConstraint(this, skeleton); + } + }; + var PositionMode = /* @__PURE__ */ ((PositionMode2) => { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + return PositionMode2; + })(PositionMode || {}); + var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + return SpacingMode2; + })(SpacingMode || {}); + var RotateMode = /* @__PURE__ */ ((RotateMode2) => { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + return RotateMode2; + })(RotateMode || {}); + + // spine-core/src/PathConstraint.ts + var PathConstraint = class _PathConstraint extends Constraint { + static NONE = -1; + static BEFORE = -2; + static AFTER = -3; + /** The path constraint's setup pose data. */ + data; + /** The bones that will be modified by this path constraint. */ + bones; + /** The slot whose path attachment will be used to constrained the bones. */ + slot; + spaces = []; + positions = []; + world = []; + curves = []; + lengths = []; + segments = []; + constructor(data, skeleton) { + super(data, new PathConstraintPose(), new PathConstraintPose()); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = []; + for (const boneData of this.data.bones) + this.bones.push(skeleton.bones[boneData.index].constrainedPose); + this.slot = skeleton.slots[data.slot.index]; + } + copy(skeleton) { + var copy = new _PathConstraint(this.data, skeleton); + copy.pose.set(this.pose); + return copy; + } + update(skeleton, physics) { + const attachment = this.slot.appliedPose.attachment; + if (!(attachment instanceof PathAttachment)) return; + const p = this.appliedPose; + const mixRotate = p.mixRotate, mixX = p.mixX, mixY = p.mixY; + if (mixRotate === 0 && mixX === 0 && mixY === 0) return; + const data = this.data; + const tangents = data.rotateMode === 0 /* Tangent */, scale = data.rotateMode === 2 /* ChainScale */; + const bones = this.bones; + const boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + const spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + const spacing = p.spacing; + switch (data.spacingMode) { + case 2 /* Percent */: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + const bone = bones[i]; + const setupLength = bone.bone.data.length; + const x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case 3 /* Proportional */: { + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + const bone = bones[i]; + const setupLength = bone.bone.data.length; + if (setupLength < MathUtils.epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + const x = setupLength * bone.a, y = setupLength * bone.c; + const length = Math.sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + } + default: { + const lengthSpacing = data.spacingMode === 0 /* Length */; + for (let i = 0, n = spacesCount - 1; i < n; ) { + const bone = bones[i]; + const setupLength = bone.bone.data.length; + if (setupLength < MathUtils.epsilon) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + const x = setupLength * bone.a, y = setupLength * bone.c; + const length = Math.sqrt(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = (lengthSpacing ? Math.max(0, setupLength + spacing) : spacing) * length / setupLength; + } + } + } + } + const positions = this.computeWorldPositions(skeleton, attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation === 0) + tip = data.rotateMode === 1 /* Chain */; + else { + tip = false; + const bone = this.slot.bone.appliedPose; + offsetRotation *= bone.a * bone.d - bone.b * bone.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, ip = 3; i < boneCount; i++, ip += 3) { + const bone = bones[i]; + bone.modifyWorld(skeleton); + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + const x = positions[ip], y = positions[ip + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + const length = lengths[i]; + if (length !== 0) { + const s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[ip - 1]; + else if (spaces[i + 1] === 0) + r = positions[ip + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + const length = bone.bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + } + } + computeWorldPositions(skeleton, path, spacesCount, tangents) { + const slot = this.slot; + let position = this.appliedPose.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world; + const closed = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + const lengths = path.lengths; + curveCount -= closed ? 1 : 2; + const pathLength2 = lengths[curveCount]; + if (this.data.positionMode === 1 /* Percent */) position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier2 = pathLength2; + break; + case 3 /* Proportional */: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + const space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed) { + p %= pathLength2; + if (p < 0) p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve !== _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(skeleton, slot, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve !== _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(skeleton, slot, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + const length = lengths[curve]; + if (p > length) continue; + if (curve === 0) + p /= length; + else { + const prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve !== prevCurve) { + prevCurve = curve; + if (closed && curve === curveCount) { + path.computeWorldVertices(skeleton, slot, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(skeleton, slot, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(skeleton, slot, curve * 6 + 2, 8, world, 0, 2); + } + this.addCurvePosition( + p, + world[0], + world[1], + world[2], + world[3], + world[4], + world[5], + world[6], + world[7], + out, + o, + tangents || i > 0 && space === 0 + ); + } + return out; + } + if (closed) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(skeleton, slot, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(skeleton, slot, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(skeleton, slot, 2, verticesLength, world, 0, 2); + } + const curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode === 1 /* Percent */) position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier = pathLength; + break; + case 3 /* Proportional */: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + const segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + const space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed) { + p %= pathLength; + if (p < 0) p += pathLength; + curve = 0; + segment = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + const length = curves[curve]; + if (p > length) continue; + if (curve === 0) + p /= length; + else { + const prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve !== prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + const length = segments[segment]; + if (p > length) continue; + if (segment === 0) + p /= length; + else { + const prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space === 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + const x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + const x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p === 0 || Number.isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + const tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + const ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + const x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } + sort(skeleton) { + const slotIndex = this.slot.data.index; + const slotBone = this.slot.bone; + if (skeleton.skin != null) this.sortPathSlot(skeleton, skeleton.skin, slotIndex, slotBone); + if (skeleton.data.defaultSkin != null && skeleton.data.defaultSkin !== skeleton.skin) + this.sortPathSlot(skeleton, skeleton.data.defaultSkin, slotIndex, slotBone); + this.sortPath(skeleton, this.slot.pose.attachment, slotBone); + const bones = this.bones; + const boneCount = this.bones.length; + for (let i = 0; i < boneCount; i++) { + const bone = bones[i].bone; + skeleton.sortBone(bone); + skeleton.constrained(bone); + } + skeleton._updateCache.push(this); + for (let i = 0; i < boneCount; i++) + skeleton.sortReset(bones[i].bone.children); + for (let i = 0; i < boneCount; i++) + bones[i].bone.sorted = true; + } + sortPathSlot(skeleton, skin, slotIndex, slotBone) { + const entries = skin.getAttachments(); + for (let i = 0, n = entries.length; i < n; i++) { + const entry = entries[i]; + if (entry.slotIndex === slotIndex) this.sortPath(skeleton, entry.attachment, slotBone); + } + } + sortPath(skeleton, attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) return; + const pathBones = attachment.bones; + if (pathBones == null) + skeleton.sortBone(slotBone); + else { + const bones = skeleton.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + skeleton.sortBone(bones[pathBones[i++]]); + } + } + } + isSourceActive() { + return this.slot.bone.active; + } + }; + + // spine-core/src/Physics.ts + var Physics = /* @__PURE__ */ ((Physics2) => { + Physics2[Physics2["none"] = 0] = "none"; + Physics2[Physics2["reset"] = 1] = "reset"; + Physics2[Physics2["update"] = 2] = "update"; + Physics2[Physics2["pose"] = 3] = "pose"; + return Physics2; + })(Physics || {}); + + // spine-core/src/PhysicsConstraintPose.ts + var PhysicsConstraintPose = class { + /** Controls how much bone movement is converted into physics movement. */ + inertia = 0; + /** The amount of force used to return properties to the unconstrained value. */ + strength = 0; + /** Reduces the speed of physics movements, with more of a reduction at higher speeds. */ + damping = 0; + /** Determines susceptibility to acceleration. */ + massInverse = 0; + /** Applies a constant force along the {@link Skeleton.windX}, {@link Skeleton.windY} vector. */ + wind = 0; + /** Applies a constant force along the {@link Skeleton.gravityX}, {@link Skeleton.gravityY} vector. */ + gravity = 0; + /** A percentage (0+) that controls the mix between the constrained and unconstrained poses. */ + mix = 0; + set(pose) { + this.inertia = pose.inertia; + this.strength = pose.strength; + this.damping = pose.damping; + this.massInverse = pose.massInverse; + this.wind = pose.wind; + this.gravity = pose.gravity; + this.mix = pose.mix; + } + }; + + // spine-core/src/SlotPose.ts + var SlotPose = class { + /** The color used to tint the slot's attachment. If {@link darkColor} is set, this is used as the light color for two color + * tinting. */ + color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + /** The current attachment for the slot, or null if the slot has no attachment. */ + attachment = null; + // Not used in setup pose. + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence.getSetupIndex}. */ + sequenceIndex = 0; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * + * See {@link VertexAttachment.computeWorldVertices} and + * {@link DeformTimeline}. */ + deform = []; + SlotPose() { + } + set(pose) { + if (pose == null) throw new Error("pose cannot be null."); + this.color.setFromColor(pose.color); + if (this.darkColor != null && pose.darkColor != null) this.darkColor.setFromColor(pose.darkColor); + this.attachment = pose.attachment; + this.sequenceIndex = pose.sequenceIndex; + this.deform.length = 0; + this.deform.push(...pose.deform); + } + /** The current attachment for the slot, or null if the slot has no attachment. */ + getAttachment() { + return this.attachment; + } + /** Sets the slot's attachment and, if the attachment changed, resets {@link sequenceIndex} and clears the {@link deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment.getTimelineAttachment} as the + * specified attachment. */ + setAttachment(attachment) { + if (this.attachment === attachment) return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment !== this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + }; + + // spine-core/src/Slot.ts + var Slot = class _Slot extends Posed { + skeleton; + /** The bone this slot belongs to. */ + bone; + attachmentState = 0; + constructor(data, skeleton) { + super(data, new SlotPose(), new SlotPose()); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.skeleton = skeleton; + this.bone = skeleton.bones[data.boneData.index]; + if (data.setupPose.darkColor != null) { + this.pose.darkColor = new Color(); + this.constrainedPose.darkColor = new Color(); + } + this.setupPose(); + } + /** Copy constructor. */ + copy(slot, bone, skeleton) { + const copy = new _Slot(slot.data, this.skeleton); + if (this.data.setupPose.darkColor != null) { + copy.pose.darkColor = new Color(); + copy.constrainedPose.darkColor = new Color(); + } + copy.pose.set(slot.pose); + return copy; + } + setupPose() { + this.pose.color.setFromColor(this.data.setupPose.color); + if (this.pose.darkColor) this.pose.darkColor.setFromColor(this.data.setupPose.darkColor); + this.pose.sequenceIndex = this.data.setupPose.sequenceIndex; + if (!this.data.attachmentName) + this.pose.setAttachment(null); + else { + this.pose.attachment = null; + this.pose.setAttachment(this.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } + }; + + // spine-core/src/Skeleton.ts + var Skeleton = class _Skeleton { + static quadTriangles = [0, 1, 2, 2, 3, 0]; + static yDown = false; + static get yDir() { + return _Skeleton.yDown ? -1 : 1; + } + /** The skeleton's setup pose data. */ + data; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones; + /** The skeleton's slots. To add a slot, also add it to {@link DrawOrder.pose}. */ + slots; + /** The skeleton's draw order. Use {@link DrawOrder.appliedPose} for rendering and {@link DrawOrder.pose} for changing the draw + * order. */ + drawOrder; + /** The skeleton's constraints. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constraints; + /** The skeleton's physics constraints. */ + physics; + /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link updateCache}. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + _updateCache = []; + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + resetCache = []; + /** The skeleton's current skin. May be null. */ + skin = null; + /** The color to tint all the skeleton's attachments. */ + color; + /** Scales the entire skeleton on the X axis. + * + * Bones that do not inherit scale are still affected by this property. */ + scaleX = 1; + _scaleY = 1; + /** Scales the entire skeleton on the Y axis. + * + * Bones that do not inherit scale are still affected by this property. */ + get scaleY() { + return this._scaleY * _Skeleton.yDir; + } + set scaleY(scaleY) { + this._scaleY = scaleY; + } + /** Sets the skeleton X position, which is added to the root bone worldX position. + * + * Bones that do not inherit translation are still affected by this property. */ + x = 0; + /** Sets the skeleton Y position, which is added to the root bone worldY position. + * + * Bones that do not inherit translation are still affected by this property. */ + y = 0; + /** Returns the skeleton's time, is used for time-based manipulations, such as {@link PhysicsConstraint}. + * + * See {@link _update}. */ + time = 0; + /** The x component of a vector that defines the direction {@link PhysicsConstraintPose.wind} is applied. */ + windX = 1; + /** The y component of a vector that defines the direction {@link PhysicsConstraintPose.wind} is applied. */ + windY = 0; + /** The x component of a vector that defines the direction {@link PhysicsConstraintPose.gravity} is applied. */ + gravityX = 0; + /** The y component of a vector that defines the direction {@link PhysicsConstraintPose.gravity} is applied. */ + gravityY = 1; + _update = 0; + constructor(data) { + if (!data) throw new Error("data cannot be null."); + this.data = data; + this.bones = []; + for (let i = 0; i < data.bones.length; i++) { + const boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, null); + else { + const parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = []; + for (const slotData of this.data.slots) + this.slots.push(new Slot(slotData, this)); + this.drawOrder = new DrawOrder(this.slots); + this.physics = []; + this.constraints = []; + for (const constraintData of this.data.constraints) { + const constraint = constraintData.create(this); + if (constraint instanceof PhysicsConstraint) this.physics.push(constraint); + this.constraints.push(constraint); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + /** Caches information about bones and constraints. Must be called if the {@link skin} is modified or if bones, constraints, + * or weighted path attachments are added or removed. */ + updateCache() { + this._updateCache.length = 0; + this.resetCache.length = 0; + this.drawOrder.unconstrained(); + const slots = this.slots; + for (let i = 0, n2 = slots.length; i < n2; i++) + slots[i].unconstrained(); + const bones = this.bones; + const boneCount = bones.length; + for (let i = 0, n2 = boneCount; i < n2; i++) { + const bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + bone.unconstrained(); + } + if (this.skin) { + const skinBones = this.skin.bones; + for (let i = 0, n2 = this.skin.bones.length; i < n2; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + const constraints = this.constraints; + let n = this.constraints.length; + for (let i = 0; i < n; i++) + constraints[i].unconstrained(); + for (let i = 0; i < n; i++) { + const constraint = constraints[i]; + constraint.active = constraint.isSourceActive() && (!constraint.data.skinRequired || this.skin != null && this.skin.constraints.includes(constraint.data)); + if (constraint.active) constraint.sort(this); + } + for (let i = 0; i < boneCount; i++) + this.sortBone(bones[i]); + n = this._updateCache.length; + for (let i = 0; i < n; i++) { + const updateable = this._updateCache[i]; + if (updateable instanceof Bone) this._updateCache[i] = updateable.appliedPose; + } + } + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constrained(object) { + if (object.pose === object.appliedPose) { + object.constrained(); + this.resetCache.push(object); + } + } + sortBone(bone) { + if (bone.sorted || !bone.active) return; + const parent = bone.parent; + if (parent) this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + const bone = bones[i]; + if (bone.active) { + if (bone.sorted) this.sortReset(bone.children); + bone.sorted = false; + } + } + } + /** Updates the world transform for each bone and applies all constraints. + * + * See World transforms in the Spine + * Runtimes Guide. */ + updateWorldTransform(physics) { + this._update++; + if (this.drawOrder.appliedPose === this.drawOrder.constrainedPose) this.drawOrder.resetConstrained(); + const resetCache = this.resetCache; + for (let i = 0, n = this.resetCache.length; i < n; i++) + resetCache[i].resetConstrained(); + const updateCache = this._updateCache; + for (let i = 0, n = this._updateCache.length; i < n; i++) + updateCache[i].update(this, physics); + } + /** Sets the bones, constraints, and slots to their setup pose values. */ + setupPose() { + this.setupPoseBones(); + this.setupPoseSlots(); + } + /** Sets the bones and constraints to their setup pose values. */ + setupPoseBones() { + const bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) + bones[i].setupPose(); + const constraints = this.constraints; + for (let i = 0, n = constraints.length; i < n; i++) + constraints[i].setupPose(); + } + /** Sets the slots and draw order to their setup pose values. */ + setupPoseSlots() { + this.drawOrder.setupPose(); + const slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setupPose(); + } + /** Returns the root bone, or null if the skeleton has no bones. */ + getRootBone() { + if (this.bones.length === 0) return null; + return this.bones[0]; + } + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * repeatedly. */ + findBone(boneName) { + if (!boneName) throw new Error("boneName cannot be null."); + const bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name === boneName) return bones[i]; + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. */ + findSlot(slotName) { + if (!slotName) throw new Error("slotName cannot be null."); + const slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name === slotName) return slots[i]; + return null; + } + setSkin(newSkin) { + if (typeof newSkin === "string") + this.setSkinByName(newSkin); + else + this.setSkinBySkin(newSkin); + } + setSkinByName(skinName) { + const skin = this.data.findSkin(skinName); + if (!skin) throw new Error(`Skin not found: ${skinName}`); + this.setSkin(skin); + } + setSkinBySkin(newSkin) { + if (newSkin === this.skin) return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + const slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + const slot = slots[i]; + const name = slot.data.attachmentName; + if (name) { + const attachment = newSkin.getAttachment(i, name); + if (attachment) slot.pose.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + getAttachment(slotNameOrIndex, placeholder) { + if (typeof slotNameOrIndex === "string") + return this.getAttachmentByName(slotNameOrIndex, placeholder); + return this.getAttachmentByIndex(slotNameOrIndex, placeholder); + } + /** Finds an attachment by looking in the {@link skin} and {@link SkeletonData.defaultSkin} using the slot name and attachment + * name. + * + * See {@link getAttachment}. + * @returns May be null. */ + getAttachmentByName(slotName, placeholder) { + const slot = this.data.findSlot(slotName); + if (!slot) throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.index, placeholder); + } + /** Finds an attachment by looking in the {@link skin} and {@link SkeletonData.defaultSkin} using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. + * @returns May be null. */ + getAttachmentByIndex(slotIndex, placeholder) { + if (!placeholder) throw new Error("placeholder cannot be null."); + if (this.skin) { + const attachment = this.skin.getAttachment(slotIndex, placeholder); + if (attachment) return attachment; + } + if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, placeholder); + return null; + } + /** A convenience method to set an attachment by finding the slot with {@link findSlot}, finding the attachment with + * {@link getAttachment}, then setting the slot's {@link Slot.attachment}. + * @param placeholder May be null to clear the slot's attachment. */ + setAttachment(slotName, placeholder) { + if (!slotName) throw new Error("slotName cannot be null."); + const slot = this.findSlot(slotName); + if (!slot) throw new Error(`Slot not found: ${slotName}`); + let attachment = null; + if (placeholder) { + attachment = this.getAttachment(slot.data.index, placeholder); + if (!attachment) + throw new Error(`Attachment not found: ${placeholder}, for slot: ${slotName}`); + } + slot.pose.setAttachment(attachment); + } + /** Finds a constraint of the specified type by comparing each constraints's name. It is more efficient to cache the results of + * this method than to call it multiple times. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + findConstraint(constraintName, type) { + if (constraintName == null) throw new Error("constraintName cannot be null."); + if (type == null) throw new Error("type cannot be null."); + const constraints = this.constraints; + for (let i = 0, n = constraints.length; i < n; i++) { + const constraint = constraints[i]; + if (constraint instanceof type && constraint.data.name === constraintName) return constraint; + } + return null; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. */ + getBoundsRect(clipper) { + const offset = new Vector2(); + const size = new Vector2(); + this.getBounds(offset, size, void 0, clipper); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. Optionally applies + * clipping. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. + * @param clipper {@link SkeletonClipping} to use. If `null`, no clipping is applied. */ + getBounds(offset, size, temp = new Array(2), clipper = null) { + if (!offset) throw new Error("offset cannot be null."); + if (!size) throw new Error("size cannot be null."); + const drawOrder = this.drawOrder.appliedPose; + const slots = drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + const slot = slots[i]; + if (!slot.bone.active) continue; + let verticesLength = 0; + let vertices = null; + let triangles = null; + const attachment = slot.appliedPose.attachment; + if (attachment) { + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot, attachment.getOffsets(slot.appliedPose), vertices, 0, 2); + triangles = _Skeleton.quadTriangles; + } else if (attachment instanceof MeshAttachment) { + verticesLength = attachment.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(this, slot, 0, verticesLength, vertices, 0, 2); + triangles = attachment.triangles; + } else if (attachment instanceof ClippingAttachment && clipper) { + clipper.clipEnd(slot); + clipper.clipStart(this, slot, attachment); + continue; + } + if (vertices && triangles) { + if (clipper?.isClipping() && clipper.clipTriangles(vertices, triangles, triangles.length)) { + vertices = clipper.clippedVertices; + verticesLength = clipper.clippedVertices.length; + } + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + const x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + if (clipper) clipper.clipEnd(slot); + } + if (clipper) clipper.clipEnd(); + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + /** Scales the entire skeleton on the X and Y axes. + * + * Bones that do not inherit scale are still affected by this property. */ + setScale(scaleX, scaleY) { + this.scaleX = scaleX; + this.scaleY = scaleY; + } + /** Sets the skeleton X and Y position, which is added to the root bone worldX and worldY position. + * + * Bones that do not inherit translation are still affected by this property. */ + setPosition(x, y) { + this.x = x; + this.y = y; + } + /** Increments the skeleton's {@link time}. */ + update(delta) { + this.time += delta; + } + /** Calls {@link PhysicsConstraint.translate} for each physics constraint. */ + physicsTranslate(x, y) { + const constraints = this.physics; + for (let i = 0, n = constraints.length; i < n; i++) + constraints[i].translate(x, y); + } + /** Calls {@link PhysicsConstraint.rotate} for each physics constraint. */ + physicsRotate(x, y, degrees) { + const constraints = this.physics; + for (let i = 0, n = constraints.length; i < n; i++) + constraints[i].rotate(x, y, degrees); + } + }; + + // spine-core/src/PhysicsConstraint.ts + var PhysicsConstraint = class _PhysicsConstraint extends Constraint { + bone; + _reset = true; + ux = 0; + uy = 0; + cx = 0; + cy = 0; + tx = 0; + ty = 0; + xOffset = 0; + xLag = 0; + xVelocity = 0; + yOffset = 0; + yLag = 0; + yVelocity = 0; + rotateOffset = 0; + rotateLag = 0; + rotateVelocity = 0; + scaleOffset = 0; + scaleLag = 0; + scaleVelocity = 0; + remaining = 0; + lastTime = 0; + constructor(data, skeleton) { + super(data, new PhysicsConstraintPose(), new PhysicsConstraintPose()); + if (skeleton == null) throw new Error("skeleton cannot be null."); + this.bone = skeleton.bones[data.bone.index].constrainedPose; + } + copy(skeleton) { + var copy = new _PhysicsConstraint(this.data, skeleton); + copy.pose.set(this.pose); + return copy; + } + /** Resets all physics state that was the result of previous movement. Use this after moving a bone to prevent physics from + * reacting to the movement. */ + reset(skeleton) { + this.remaining = 0; + this.lastTime = skeleton.time; + this._reset = true; + this.xOffset = 0; + this.xLag = 0; + this.xVelocity = 0; + this.yOffset = 0; + this.yLag = 0; + this.yVelocity = 0; + this.rotateOffset = 0; + this.rotateLag = 0; + this.rotateVelocity = 0; + this.scaleOffset = 0; + this.scaleLag = 0; + this.scaleVelocity = 0; + } + /** Translates the physics constraint so the next {@link update} forces are applied as if the bone moved an + * additional amount in world space. */ + translate(x, y) { + this.ux -= x; + this.uy -= y; + this.cx -= x; + this.cy -= y; + } + /** Rotates the physics constraint so the next {@link update} forces are applied as if the bone rotated + * around the specified point in world space. */ + rotate(x, y, degrees) { + const r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const dx = this.cx - x, dy = this.cy - y; + this.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); + } + /** Applies the constraint to the constrained bones. */ + update(skeleton, physics) { + const p = this.appliedPose; + const mix = p.mix; + if (mix === 0) return; + const x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0; + const bone = this.bone; + let l = bone.bone.data.length, t = this.data.step, z = 0; + if (physics === 0 /* none */) return; + bone.modifyWorld(skeleton); + switch (physics) { + // biome-ignore lint/suspicious/noFallthroughSwitchClause: fall through expected + case 1 /* reset */: + this.reset(skeleton); + // Fall through. + case 2 /* update */: { + const delta = Math.max(skeleton.time - this.lastTime, 0), aa = this.remaining; + this.remaining += delta; + this.lastTime = skeleton.time; + const bx = bone.worldX, by = bone.worldY; + if (this._reset) { + this._reset = false; + this.ux = bx; + this.uy = by; + } else { + let a = this.remaining, i = p.inertia, f = skeleton.data.referenceScale, d = -1, m = 0, e = 0, qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY); + qx *= Math.abs(skeleton.scaleX); + if (x || y) { + if (x) { + const u = (this.ux - bx) * i; + this.xOffset += u > qx ? qx : u < -qx ? -qx : u; + this.ux = bx; + } + if (y) { + const u = (this.uy - by) * i; + this.yOffset += u > qy ? qy : u < -qy ? -qy : u; + this.uy = by; + } + if (a >= t) { + const xs = this.xOffset, ys = this.yOffset; + d = p.damping ** (60 * t); + m = t * p.massInverse; + e = p.strength; + const w = f * p.wind, g = f * p.gravity; + const ax = (w * skeleton.windX + g * skeleton.gravityX) * skeleton.scaleX; + const ay = (w * skeleton.windY + g * skeleton.gravityY) * skeleton.scaleY; + do { + if (x) { + this.xVelocity += (ax - this.xOffset * e) * m; + this.xOffset += this.xVelocity * t; + this.xVelocity *= d; + } + if (y) { + this.yVelocity -= (ay + this.yOffset * e) * m; + this.yOffset += this.yVelocity * t; + this.yVelocity *= d; + } + a -= t; + } while (a >= t); + this.xLag = this.xOffset - xs; + this.yLag = this.yOffset - ys; + } + z = Math.max(0, 1 - a / t); + if (x) bone.worldX += (this.xOffset - this.xLag * z) * mix * this.data.x; + if (y) bone.worldY += (this.yOffset - this.yLag * z) * mix * this.data.y; + } + if (rotateOrShearX || scaleX) { + let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0, dx = this.cx - bone.worldX, dy = this.cy - bone.worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx) + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy) + dy = -qy; + a = this.remaining; + if (rotateOrShearX) { + mr = (this.data.rotate + this.data.shearX) * mix; + z = this.rotateLag * Math.max(0, 1 - aa / t); + let r = Math.atan2(dy + this.ty, dx + this.tx) - ca - (this.rotateOffset - z) * mr; + this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; + r = (this.rotateOffset - z) * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + if (scaleX) { + r = l * bone.getWorldScaleX(); + if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = Math.cos(ca); + s = Math.sin(ca); + const r = l * bone.getWorldScaleX() - this.scaleLag * Math.max(0, 1 - aa / t); + if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + } + if (a >= t) { + if (d === -1) { + d = p.damping ** (60 * t); + m = t * p.massInverse; + e = p.strength; + } + const ax = p.wind * skeleton.windX + p.gravity * skeleton.gravityX; + const ay = (p.wind * skeleton.windY + p.gravity * skeleton.gravityY) * Skeleton.yDir; + const rs = this.rotateOffset, ss = this.scaleOffset, h = l / f; + while (true) { + a -= t; + if (scaleX) { + this.scaleVelocity += (ax * c - ay * s - this.scaleOffset * e) * m; + this.scaleOffset += this.scaleVelocity * t; + this.scaleVelocity *= d; + } + if (rotateOrShearX) { + this.rotateVelocity -= ((ax * s + ay * c) * h + this.rotateOffset * e) * m; + this.rotateOffset += this.rotateVelocity * t; + this.rotateVelocity *= d; + if (a < t) break; + const r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + } else if (a < t) + break; + } + this.rotateLag = this.rotateOffset - rs; + this.scaleLag = this.scaleOffset - ss; + } + z = Math.max(0, 1 - a / t); + } + this.remaining = a; + } + this.cx = bone.worldX; + this.cy = bone.worldY; + break; + } + case 3 /* pose */: + z = Math.max(0, 1 - this.remaining / t); + if (x) bone.worldX += (this.xOffset - this.xLag * z) * mix * this.data.x; + if (y) bone.worldY += (this.yOffset - this.yLag * z) * mix * this.data.y; + } + if (rotateOrShearX) { + let o = (this.rotateOffset - this.rotateLag * z) * mix, s = 0, c = 0, a = 0; + if (this.data.shearX > 0) { + let r = 0; + if (this.data.rotate > 0) { + r = o * this.data.rotate; + s = Math.sin(r); + c = Math.cos(r); + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + r += o * this.data.shearX; + s = Math.sin(r); + c = Math.cos(r); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + } else { + o *= this.data.rotate; + s = Math.sin(o); + c = Math.cos(o); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + } + if (scaleX) { + let s = 1 + (this.scaleOffset - this.scaleLag * z) * mix * this.data.scaleX; + bone.a *= s; + bone.c *= s; + switch (this.data.scaleYMode) { + case 1 /* Uniform */: + bone.b *= s; + bone.d *= s; + break; + case 2 /* Volume */: + s = Math.abs(s); + s = s >= 0.7 ? 1 / s : 4 - 3.67347 * s; + bone.b *= s; + bone.d *= s; + } + } + if (physics !== 3 /* pose */) { + this.tx = l * bone.a; + this.ty = l * bone.c; + } + } + sort(skeleton) { + const bone = this.bone.bone; + skeleton.sortBone(bone); + skeleton._updateCache.push(this); + skeleton.sortReset(bone.children); + skeleton.constrained(bone); + } + isSourceActive() { + return this.bone.bone.active; + } + }; + + // spine-core/src/PhysicsConstraintData.ts + var PhysicsConstraintData = class extends ConstraintData { + /** The bone constrained by this physics constraint. */ + set bone(boneData) { + this._bone = boneData; + } + get bone() { + if (!this._bone) throw new Error("BoneData not set."); + else return this._bone; + } + _bone = null; + /** Physics influence on x translation, 0-1. */ + x = 0; + /** Physics influence on y translation, 0-1. */ + y = 0; + /** Physics influence on rotation, 0-1. */ + rotate = 0; + /** Physics influence on scaleX, 0-1. */ + scaleX = 0; + /** Physics influence on shearX, 0-1. */ + shearX = 0; + /** Movement greater than the limit will not have a greater affect on physics. */ + limit = 0; + /** The time in milliseconds required to advanced the physics simulation one step. */ + step = 0; + /** True when this constraint's inertia is controlled by global slider timelines. */ + inertiaGlobal = false; + /** True when this constraint's strength is controlled by global slider timelines. */ + strengthGlobal = false; + /** True when this constraint's damping is controlled by global slider timelines. */ + dampingGlobal = false; + /** True when this constraint's mass is controlled by global slider timelines. */ + massGlobal = false; + /** True when this constraint's wind is controlled by global slider timelines. */ + windGlobal = false; + /** True when this constraint's gravity is controlled by global slider timelines. */ + gravityGlobal = false; + /** True when this constraint's mix is controlled by global slider timelines. */ + mixGlobal = false; + /** Determines how the {@link BonePose.scaleY} changes when {@link BonePose.scaleX} sets + * {@link BonePose.scaleX}. */ + _scaleYMode = 0 /* None */; + get scaleYMode() { + return this._scaleYMode; + } + set scaleYMode(scaleYMode) { + if (scaleYMode == null) throw new Error("scaleYMode cannot be null."); + this._scaleYMode = scaleYMode; + } + constructor(name) { + super(name, new PhysicsConstraintPose()); + } + create(skeleton) { + return new PhysicsConstraint(this, skeleton); + } + }; + + // spine-core/src/polyfills.ts + (() => { + if (typeof Math.fround === "undefined") { + Math.fround = /* @__PURE__ */ ((array) => (x) => { + array[0] = x; + return array[0]; + })(new Float32Array(1)); + } + })(); + + // spine-core/src/SliderPose.ts + var SliderPose = class { + /** The time in the {@link SliderData.animation} to apply the animation. */ + time = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained poses. */ + mix = 0; + set(pose) { + this.time = pose.time; + this.mix = pose.mix; + } + }; + + // spine-core/src/Slider.ts + var Slider = class _Slider extends Constraint { + static offsets = [0, 0, 0, 0, 0, 0]; + /** When set, the bone's transform property is used to set the slider's {@link SliderPose.time}. */ + bone = null; + constructor(data, skeleton) { + super(data, new SliderPose(), new SliderPose()); + if (!skeleton) throw new Error("skeleton cannot be null."); + if (data.bone != null) this.bone = skeleton.bones[data.bone.index]; + } + copy(skeleton) { + var copy = new _Slider(this.data, skeleton); + copy.pose.set(this.pose); + return copy; + } + update(skeleton, physics) { + const p = this.appliedPose; + if (p.mix === 0) return; + const data = this.data, animation = data.animation, bone = this.bone; + if (bone !== null) { + if (!bone.active) return; + if (data.local) bone.appliedPose.validateLocalTransform(skeleton); + p.time = data.offset + (data.property.value(skeleton, bone.appliedPose, data.local, _Slider.offsets) - data.property.offset) * data.scale; + if (data.loop) + p.time = animation.duration + p.time % animation.duration; + else + p.time = Math.max(0, p.time); + } + const bones = skeleton.bones; + const indices = animation.bones; + for (let i = 0, n = animation.bones.length; i < n; i++) + bones[indices[i]].appliedPose.modifyLocal(skeleton); + animation.apply(skeleton, p.time, p.time, data.loop, null, p.mix, 0 /* current */, data.additive, false, true); + } + sort(skeleton) { + const bone = this.bone; + const data = this.data; + if (bone && !data.local) skeleton.sortBone(bone); + skeleton._updateCache.push(this); + const bones = skeleton.bones; + const indices = data.animation.bones; + for (let i = 0, n = data.animation.bones.length; i < n; i++) { + const bone2 = bones[indices[i]]; + bone2.sorted = false; + skeleton.sortReset(bone2.children); + skeleton.constrained(bone2); + } + const timelines = data.animation.timelines; + const slots = skeleton.slots; + const constraints = skeleton.constraints; + const physics = skeleton.physics; + const physicsCount = skeleton.physics.length; + for (let i = 0, n = data.animation.timelines.length; i < n; i++) { + const t = timelines[i]; + if (isSlotTimeline(t)) + skeleton.constrained(slots[t.slotIndex]); + else if (t instanceof DrawOrderTimeline || t instanceof DrawOrderFolderTimeline) + skeleton.drawOrder.constrained(); + else if (t instanceof PhysicsConstraintTimeline) { + if (t.constraintIndex === -1) { + for (let ii = 0; ii < physicsCount; ii++) + skeleton.constrained(physics[ii]); + } else + skeleton.constrained(constraints[t.constraintIndex]); + } else if (isConstraintTimeline(t)) { + const constraintIndex = t.constraintIndex; + if (constraintIndex !== -1) skeleton.constrained(constraints[constraintIndex]); + } + } + } + }; + + // spine-core/src/SliderData.ts + var SliderData = class extends ConstraintData { + /** The animation the slider will apply. */ + animation; + /** When true, the animation is applied by adding it to the current pose rather than overwriting it. */ + additive = false; + /** When true, the animation repeats after its duration, otherwise the last frame is used. */ + loop = false; + /** When set, the bone's transform property is used to set the slider's {@link SliderPose.time}. */ + bone = null; + /** When a bone is set, the specified transform property is used to set the slider's {@link SliderPose.time}. */ + property; + /** When a bone is set, this is the scale of the {@link property} value in relation to the slider time. */ + scale = 0; + /** When a bone is set, the offset is added to the property. */ + offset = 0; + /** When true and a bone is set, the bone's local transform property is read instead of its world transform. */ + local = false; + // Nonessential. + /** When a bone is set, the maximum slider time for the bone property range, or 0 if nonessential data was not exported. */ + max = 0; + constructor(name) { + super(name, new SliderPose()); + } + create(skeleton) { + return new Slider(this, skeleton); + } + }; + + // spine-core/src/SkeletonData.ts + var SkeletonData = class { + /** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */ + name = null; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones = []; + // Ordered parents first. + /** The skeleton's slots in the setup pose draw order. */ + slots = []; + // Setup pose draw order. + skins = []; + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See {@link Skeleton.getAttachmentByName}. + * May be null. */ + defaultSkin = null; + /** The skeleton's events. */ + events = []; + /** The skeleton's animations. */ + animations = []; + /** The skeleton's IK constraints. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constraints = []; + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + x = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + y = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ + width = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ + height = 0; + /** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default + * is 100. */ + referenceScale = 100; + /** The Spine version used to export the skeleton data, or null. */ + version = null; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */ + hash = null; + // Nonessential + /** The dopesheet FPS in Spine. Available only when nonessential data was exported. */ + fps = 30; + /** The path to the images folder as defined in Spine. Available only when nonessential data was exported. May be null. */ + imagesPath = null; + /** The path to the audio folder as defined in Spine. Available only when nonessential data was exported. May be null. */ + audioPath = null; + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findBone(boneName) { + if (!boneName) throw new Error("boneName cannot be null."); + const bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) + if (bones[i].name === boneName) return bones[i]; + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) throw new Error("slotName cannot be null."); + const slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) + if (slots[i].name === slotName) return slots[i]; + return null; + } + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSkin(skinName) { + if (!skinName) throw new Error("skinName cannot be null."); + const skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) + if (skins[i].name === skinName) return skins[i]; + return null; + } + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findEvent(eventDataName) { + if (!eventDataName) throw new Error("eventDataName cannot be null."); + const events = this.events; + for (let i = 0, n = events.length; i < n; i++) + if (events[i].name === eventDataName) return events[i]; + return null; + } + /** Collects animations used by {@link SliderData slider constraints}. + * + * Slider animations are designed to be applied by slider constraints rather than on their own. Applications that have a user + * choose an animation may want to exclude them. */ + findSliderAnimations(animations) { + const constraints = this.constraints; + for (let i = 0, n = this.constraints.length; i < n; i++) { + const data = constraints[i]; + if (data instanceof SliderData && data.animation != null) animations.push(data.animation); + } + return animations; + } + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @returns May be null. */ + findAnimation(animationName) { + if (!animationName) throw new Error("animationName cannot be null."); + const animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) + if (animations[i].name === animationName) return animations[i]; + return null; + } + // --- Constraints. + /** Finds a constraint of the specified type by comparing each constraints's name. It is more efficient to cache the results of + * this method than to call it multiple times. */ + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + findConstraint(constraintName, type) { + if (!constraintName) throw new Error("constraintName cannot be null."); + if (type == null) throw new Error("type cannot be null."); + const constraints = this.constraints; + for (let i = 0, n = this.constraints.length; i < n; i++) { + const constraint = constraints[i]; + if (constraint instanceof type && constraint.name === constraintName) return constraint; + } + return null; + } + }; + + // spine-core/src/Skin.ts + var SkinEntry = class { + /** The {@link Skeleton.slots} index. */ + slotIndex = 0; + placeholder; + /** The attachment for this skin entry. */ + attachment; + constructor(slotIndex = 0, placeholder, attachment) { + this.slotIndex = slotIndex; + this.placeholder = placeholder; + this.attachment = attachment; + } + }; + var Skin = class { + /** The skin's name, unique across all skins in the skeleton. + * + * See {@link SkeletonData.findSkin}. */ + name; + attachments = []; + bones = []; + // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types + constraints = []; + /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ + color = new Color(0.99607843, 0.61960787, 0.30980393, 1); + // fe9e4fff + constructor(name) { + if (!name) throw new Error("name cannot be null."); + this.name = name; + } + /** Adds an attachment to the skin for the specified slot index and name. */ + setAttachment(slotIndex, placeholder, attachment) { + if (!attachment) throw new Error("attachment cannot be null."); + const attachments = this.attachments; + if (slotIndex >= attachments.length) attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) attachments[slotIndex] = {}; + attachments[slotIndex][placeholder] = attachment; + } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + const bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] === bone) { + contained = true; + break; + } + } + if (!contained) this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + const constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] === constraint) { + contained = true; + break; + } + } + if (!contained) this.constraints.push(constraint); + } + const attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + const attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.placeholder, attachment.attachment); + } + } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + const bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] === bone) { + contained = true; + break; + } + } + if (!contained) this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + const constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] === constraint) { + contained = true; + break; + } + } + if (!contained) this.constraints.push(constraint); + } + const attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + const attachment = attachments[i]; + if (!attachment.attachment) continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.placeholder, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.placeholder, attachment.attachment); + } + } + } + /** Returns the attachment for the specified slot index and placeholder, or null. */ + getAttachment(slotIndex, placeholder) { + const dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[placeholder] : null; + } + /** Removes the attachment in the skin for the specified slot index and placeholder, if any. */ + removeAttachment(slotIndex, placeholder) { + const dictionary = this.attachments[slotIndex]; + if (dictionary) delete dictionary[placeholder]; + } + /** Returns all attachments in this skin. */ + getAttachments() { + const entries = []; + for (let i = 0; i < this.attachments.length; i++) { + const slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (const name in slotAttachments) { + const attachment = slotAttachments[name]; + if (attachment) entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + /** Returns all attachments in this skin for the specified slot index. */ + getAttachmentsForSlot(slotIndex, attachments) { + const slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (const name in slotAttachments) { + const attachment = slotAttachments[name]; + if (attachment) attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + /** Clears all attachments, bones, and constraints. */ + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + const slot = skeleton.slots[i]; + const slotAttachment = slot.pose.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + const dictionary = oldSkin.attachments[slotIndex]; + for (const placeholder in dictionary) { + const skinAttachment = dictionary[placeholder]; + if (slotAttachment === skinAttachment) { + const attachment = this.getAttachment(slotIndex, placeholder); + if (attachment) slot.pose.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } + }; + + // spine-core/src/SlotData.ts + var SlotData = class extends PosedData { + /** The index of the slot in {@link Skeleton.slots}. */ + index = 0; + /** The bone this slot belongs to. */ + boneData; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ + attachmentName = null; + /** The blend mode for drawing the slot's attachment. */ + blendMode = 0 /* Normal */; + // Nonessential. + /** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = true; + constructor(index, name, boneData) { + super(name, new SlotPose()); + if (index < 0) throw new Error("index must be >= 0."); + if (!boneData) throw new Error("boneData cannot be null."); + this.index = index; + this.boneData = boneData; + } + }; + var BlendMode = /* @__PURE__ */ ((BlendMode2) => { + BlendMode2[BlendMode2["Normal"] = 0] = "Normal"; + BlendMode2[BlendMode2["Additive"] = 1] = "Additive"; + BlendMode2[BlendMode2["Multiply"] = 2] = "Multiply"; + BlendMode2[BlendMode2["Screen"] = 3] = "Screen"; + return BlendMode2; + })(BlendMode || {}); + + // spine-core/src/TransformConstraintPose.ts + var TransformConstraintPose = class { + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained rotation. */ + mixRotate = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained translation X. */ + mixX = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained translation Y. */ + mixY = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained scale X. */ + mixScaleX = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained scale Y. */ + mixScaleY = 0; + /** A percentage (unbounded) that controls the mix between the constrained and unconstrained shear Y. */ + mixShearY = 0; + set(pose) { + this.mixRotate = pose.mixRotate; + this.mixX = pose.mixX; + this.mixY = pose.mixY; + this.mixScaleX = pose.mixScaleX; + this.mixScaleY = pose.mixScaleY; + this.mixShearY = pose.mixShearY; + } + }; + + // spine-core/src/TransformConstraint.ts + var TransformConstraint = class _TransformConstraint extends Constraint { + /** The bones that will be modified by this transform constraint. */ + bones; + /** The bone whose world transform will be copied to the constrained bones. */ + source; + constructor(data, skeleton) { + super(data, new TransformConstraintPose(), new TransformConstraintPose()); + if (!skeleton) throw new Error("skeleton cannot be null."); + this.bones = []; + for (const boneData of data.bones) + this.bones.push(skeleton.bones[boneData.index].constrainedPose); + const source = skeleton.bones[data.source.index]; + if (source == null) throw new Error("source cannot be null."); + this.source = source; + } + copy(skeleton) { + var copy = new _TransformConstraint(this.data, skeleton); + copy.pose.set(this.pose); + return copy; + } + update(skeleton, physics) { + const p = this.appliedPose; + if (p.mixRotate === 0 && p.mixX === 0 && p.mixY === 0 && p.mixScaleX === 0 && p.mixScaleY === 0 && p.mixShearY === 0) return; + const data = this.data; + const localSource = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp; + const offsets = data.offsets; + const source = this.source.appliedPose; + if (localSource) source.validateLocalTransform(skeleton); + const fromItems = data.properties; + const fn = data.properties.length; + const bones = this.bones; + for (let i = 0, n = this.bones.length; i < n; i++) { + const bone = bones[i]; + if (localTarget) + bone.modifyLocal(skeleton); + else + bone.modifyWorld(skeleton); + for (let f = 0; f < fn; f++) { + const from = fromItems[f]; + const value = from.value(skeleton, source, localSource, offsets) - from.offset; + const toItems = from.to; + for (let t = 0, tn = from.to.length; t < tn; t++) { + const to = toItems[t]; + if (to.mix(p) !== 0) { + let clamped = to.offset + value * to.scale; + if (clamp) { + if (to.offset < to.max) + clamped = MathUtils.clamp(clamped, to.offset, to.max); + else + clamped = MathUtils.clamp(clamped, to.max, to.offset); + } + to.apply(skeleton, p, bone, clamped, localTarget, additive); + } + } + } + } + } + sort(skeleton) { + if (!this.data.localSource) skeleton.sortBone(this.source); + const bones = this.bones; + const boneCount = this.bones.length; + const worldTarget = !this.data.localTarget; + if (worldTarget) { + for (let i = 0; i < boneCount; i++) + skeleton.sortBone(bones[i].bone); + } + skeleton._updateCache.push(this); + for (let i = 0; i < boneCount; i++) { + const bone = bones[i].bone; + skeleton.sortReset(bone.children); + skeleton.constrained(bone); + } + for (let i = 0; i < boneCount; i++) + bones[i].bone.sorted = worldTarget; + } + isSourceActive() { + return this.source.active; + } + }; + + // spine-core/src/TransformConstraintData.ts + var TransformConstraintData = class _TransformConstraintData extends ConstraintData { + static ROTATION = 0; + static X = 1; + static Y = 2; + static SCALEX = 3; + static SCALEY = 4; + static SHEARY = 5; + /** The bones that will be modified by this transform constraint. */ + bones = []; + /** The bone whose world transform will be copied to the constrained bones. */ + set source(source) { + this._source = source; + } + get source() { + if (!this._source) throw new Error("BoneData not set."); + else return this._source; + } + _source = null; + offsets = [0, 0, 0, 0, 0, 0]; + /** An offset added to the constrained bone X translation. */ + offsetX = 0; + /** An offset added to the constrained bone Y translation. */ + offsetY = 0; + /** Reads the source bone's local transform instead of its world transform. */ + localSource = false; + /** Sets the constrained bones' local transforms instead of their world transforms. */ + localTarget = false; + /** Adds the source bone transform to the constrained bones instead of setting it absolutely. */ + additive = false; + /** Prevents constrained bones from exceeding the ranged defined by {@link ToProperty.offset} and {@link ToProperty.max}. */ + clamp = false; + /** The mapping of transform properties to other transform properties. */ + properties = []; + constructor(name) { + super(name, new TransformConstraintPose()); + } + create(skeleton) { + return new TransformConstraint(this, skeleton); + } + /** An offset added to the constrained bone rotation. */ + getOffsetRotation() { + return this.offsets[_TransformConstraintData.ROTATION]; + } + setOffsetRotation(offsetRotation) { + this.offsets[_TransformConstraintData.ROTATION] = offsetRotation; + } + /** An offset added to the constrained bone X translation. */ + getOffsetX() { + return this.offsets[_TransformConstraintData.X]; + } + setOffsetX(offsetX) { + this.offsets[_TransformConstraintData.X] = offsetX; + } + /** An offset added to the constrained bone Y translation. */ + getOffsetY() { + return this.offsets[_TransformConstraintData.Y]; + } + setOffsetY(offsetY) { + this.offsets[_TransformConstraintData.Y] = offsetY; + } + /** An offset added to the constrained bone scaleX. */ + getOffsetScaleX() { + return this.offsets[_TransformConstraintData.SCALEX]; + } + setOffsetScaleX(offsetScaleX) { + this.offsets[_TransformConstraintData.SCALEX] = offsetScaleX; + } + /** An offset added to the constrained bone scaleY. */ + getOffsetScaleY() { + return this.offsets[_TransformConstraintData.SCALEY]; + } + setOffsetScaleY(offsetScaleY) { + this.offsets[_TransformConstraintData.SCALEY] = offsetScaleY; + } + /** An offset added to the constrained bone shearY. */ + getOffsetShearY() { + return this.offsets[_TransformConstraintData.SHEARY]; + } + setOffsetShearY(offsetShearY) { + this.offsets[_TransformConstraintData.SHEARY] = offsetShearY; + } + }; + var FromProperty = class { + /** The value of this property that corresponds to {@link ToProperty.offset}. */ + offset = 0; + /** Constrained properties. */ + to = []; + }; + var ToProperty = class { + /** The value of this property that corresponds to {@link FromProperty.offset}. */ + offset = 0; + /** The maximum value of this property when {@link TransformConstraintData.clamp clamped}. */ + max = 0; + /** The scale of the {@link FromProperty} value in relation to this property. */ + scale = 0; + }; + var FromRotate = class extends FromProperty { + value(skeleton, source, local, offsets) { + if (local) return source.rotation + offsets[TransformConstraintData.ROTATION]; + const sx = skeleton.scaleX, sy = skeleton.scaleY; + let value = Math.atan2(source.c / sy, source.a / sx) * MathUtils.radDeg + ((source.a * source.d - source.b * source.c) * sx * sy > 0 ? offsets[TransformConstraintData.ROTATION] : -offsets[TransformConstraintData.ROTATION]); + if (value < 0) value += 360; + return value; + } + }; + var ToRotate = class extends ToProperty { + mix(pose) { + return pose.mixRotate; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) + bone.rotation += (additive ? value : value - bone.rotation) * pose.mixRotate; + else { + const sx = skeleton.scaleX, sy = skeleton.scaleY, ix = 1 / sx, iy = 1 / sy; + const a = bone.a * ix, b = bone.b * ix, c = bone.c * iy, d = bone.d * iy; + value *= MathUtils.degRad; + if (!additive) value -= Math.atan2(c, a); + if (value > MathUtils.PI) + value -= MathUtils.PI2; + else if (value < -MathUtils.PI) + value += MathUtils.PI2; + value *= pose.mixRotate; + const cos = Math.cos(value), sin = Math.sin(value); + bone.a = (cos * a - sin * c) * sx; + bone.b = (cos * b - sin * d) * sx; + bone.c = (sin * a + cos * c) * sy; + bone.d = (sin * b + cos * d) * sy; + } + } + }; + var FromX = class extends FromProperty { + value(skeleton, source, local, offsets) { + return local ? source.x + offsets[TransformConstraintData.X] : (offsets[TransformConstraintData.X] * source.a + offsets[TransformConstraintData.Y] * source.b + source.worldX) / skeleton.scaleX; + } + }; + var ToX = class extends ToProperty { + mix(pose) { + return pose.mixX; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) + bone.x += (additive ? value : value - bone.x) * pose.mixX; + else { + if (!additive) value -= bone.worldX / skeleton.scaleX; + bone.worldX += value * pose.mixX * skeleton.scaleX; + } + } + }; + var FromY = class extends FromProperty { + value(skeleton, source, local, offsets) { + return local ? source.y + offsets[TransformConstraintData.Y] : (offsets[TransformConstraintData.X] * source.c + offsets[TransformConstraintData.Y] * source.d + source.worldY) / skeleton.scaleY; + } + }; + var ToY = class extends ToProperty { + mix(pose) { + return pose.mixY; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) + bone.y += (additive ? value : value - bone.y) * pose.mixY; + else { + if (!additive) value -= bone.worldY / skeleton.scaleY; + bone.worldY += value * pose.mixY * skeleton.scaleY; + } + } + }; + var FromScaleX = class extends FromProperty { + value(skeleton, source, local, offsets) { + if (local) return source.scaleX + offsets[TransformConstraintData.SCALEX]; + const a = source.a / skeleton.scaleX, c = source.c / skeleton.scaleY; + return Math.sqrt(a * a + c * c) + offsets[TransformConstraintData.SCALEX]; + } + }; + var ToScaleX = class extends ToProperty { + mix(pose) { + return pose.mixScaleX; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) { + if (additive) + bone.scaleX *= 1 + (value - 1) * pose.mixScaleX; + else if (bone.scaleX !== 0) + bone.scaleX += (value - bone.scaleX) * pose.mixScaleX; + } else if (additive) { + const s = 1 + (value - 1) * pose.mixScaleX; + bone.a *= s; + bone.c *= s; + } else { + let a = bone.a / skeleton.scaleX, c = bone.c / skeleton.scaleY, s = Math.sqrt(a * a + c * c); + if (s !== 0) { + s = 1 + (value - s) * pose.mixScaleX / s; + bone.a *= s; + bone.c *= s; + } + } + } + }; + var FromScaleY = class extends FromProperty { + value(skeleton, source, local, offsets) { + if (local) return source.scaleY + offsets[TransformConstraintData.SCALEY]; + const b = source.b / skeleton.scaleX, d = source.d / skeleton.scaleY; + return Math.sqrt(b * b + d * d) + offsets[TransformConstraintData.SCALEY]; + } + }; + var ToScaleY = class extends ToProperty { + mix(pose) { + return pose.mixScaleY; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) { + if (additive) + bone.scaleY *= 1 + (value - 1) * pose.mixScaleY; + else if (bone.scaleY !== 0) + bone.scaleY += (value - bone.scaleY) * pose.mixScaleY; + } else if (additive) { + const s = 1 + (value - 1) * pose.mixScaleY; + bone.b *= s; + bone.d *= s; + } else { + let b = bone.b / skeleton.scaleX, d = bone.d / skeleton.scaleY, s = Math.sqrt(b * b + d * d); + if (s !== 0) { + s = 1 + (value - s) * pose.mixScaleY / s; + bone.b *= s; + bone.d *= s; + } + } + } + }; + var FromShearY = class extends FromProperty { + value(skeleton, source, local, offsets) { + if (local) return source.shearY + offsets[TransformConstraintData.SHEARY]; + const ix = 1 / skeleton.scaleX, iy = 1 / skeleton.scaleY; + return (Math.atan2(source.d * iy, source.b * ix) - Math.atan2(source.c * iy, source.a * ix)) * MathUtils.radDeg - 90 + offsets[TransformConstraintData.SHEARY]; + } + }; + var ToShearY = class extends ToProperty { + mix(pose) { + return pose.mixShearY; + } + apply(skeleton, pose, bone, value, local, additive) { + if (local) { + if (!additive) value -= bone.shearY; + bone.shearY += value * pose.mixShearY; + } else { + const sx = skeleton.scaleX, sy = skeleton.scaleY, b = bone.b / sx, d = bone.d / sy, by = Math.atan2(d, b); + value = (value + 90) * MathUtils.degRad; + if (additive) + value -= MathUtils.PI / 2; + else { + value -= by - Math.atan2(bone.c / sy, bone.a / sx); + if (value > MathUtils.PI) + value -= MathUtils.PI2; + else if (value < -MathUtils.PI) + value += MathUtils.PI2; + } + value = by + value * pose.mixShearY; + const s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(value) * s * sx; + bone.d = Math.sin(value) * s * sy; + } + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + attachmentLoader; + linkedMeshes = []; + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + const scale = this.scale; + const skeletonData = new SkeletonData(); + skeletonData.name = ""; + const input = new BinaryInput(binary); + const lowHash = input.readInt32(); + const highHash = input.readInt32(); + skeletonData.hash = highHash === 0 && lowHash === 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + skeletonData.referenceScale = input.readFloat() * scale; + const nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + const str = input.readString(); + if (!str) throw new Error("String in string table must not be null."); + input.strings.push(str); + } + const bones = skeletonData.bones; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + const name = input.readString(); + if (!name) throw new Error("Bone name must not be null."); + const parent = i === 0 ? null : bones[input.readInt(true)]; + const data = new BoneData(i, name, parent); + const setup = data.setupPose; + setup.rotation = input.readFloat(); + setup.x = input.readFloat() * scale; + setup.y = input.readFloat() * scale; + setup.scaleX = input.readFloat(); + setup.scaleY = input.readFloat(); + setup.shearX = input.readFloat(); + setup.shearY = input.readFloat(); + setup.inherit = input.readByte(); + data.length = input.readFloat() * scale; + data.skinRequired = input.readBoolean(); + if (nonessential) { + Color.rgba8888ToColor(data.color, input.readInt32()); + data.icon = input.readString() ?? void 0; + data.iconSize = input.readFloat(); + data.iconRotation = input.readFloat(); + data.visible = input.readBoolean(); + } + bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + const slotName = input.readString(); + if (!slotName) throw new Error("Slot name must not be null."); + const boneData = bones[input.readInt(true)]; + const data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.setupPose.color, input.readInt32()); + const darkColor = input.readInt32(); + if (darkColor !== -1) Color.rgb888ToColor(data.setupPose.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + if (nonessential) data.visible = input.readBoolean(); + skeletonData.slots.push(data); + } + const constraints = skeletonData.constraints; + const constraintCount = input.readInt(true); + for (let i = 0; i < constraintCount; i++) { + const name = input.readString(); + if (!name) throw new Error("Constraint data name must not be null."); + let nn; + switch (input.readByte()) { + case CONSTRAINT_IK: { + const data = new IkConstraintData(name); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(bones[input.readInt(true)]); + data.target = bones[input.readInt(true)]; + const flags = input.readByte(); + data.skinRequired = (flags & 1) !== 0; + if ((flags & 2) !== 0) data.scaleYMode = input.readUnsignedByte(); + const setup = data.setupPose; + setup.bendDirection = (flags & 4) !== 0 ? -1 : 1; + setup.compress = (flags & 8) !== 0; + setup.stretch = (flags & 16) !== 0; + if ((flags & 32) !== 0) setup.mix = (flags & 64) !== 0 ? input.readFloat() : 1; + if ((flags & 128) !== 0) setup.softness = input.readFloat() * scale; + constraints.push(data); + break; + } + case CONSTRAINT_TRANSFORM: { + const data = new TransformConstraintData(name); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(bones[input.readInt(true)]); + data.source = bones[input.readInt(true)]; + let flags = input.readUnsignedByte(); + data.skinRequired = (flags & 1) !== 0; + data.localSource = (flags & 2) !== 0; + data.localTarget = (flags & 4) !== 0; + data.additive = (flags & 8) !== 0; + data.clamp = (flags & 16) !== 0; + nn = flags >> 5; + for (let ii = 0, tn; ii < nn; ii++) { + let fromScale = 1; + let from; + switch (input.readByte()) { + case 0: + from = new FromRotate(); + break; + case 1: { + fromScale = scale; + from = new FromX(); + break; + } + case 2: { + fromScale = scale; + from = new FromY(); + break; + } + case 3: + from = new FromScaleX(); + break; + case 4: + from = new FromScaleY(); + break; + case 5: + from = new FromShearY(); + break; + default: + from = null; + } + if (!from) continue; + from.offset = input.readFloat() * fromScale; + tn = input.readByte(); + for (let t = 0; t < tn; t++) { + let toScale = 1; + let to; + switch (input.readByte()) { + case 0: + to = new ToRotate(); + break; + case 1: { + toScale = scale; + to = new ToX(); + break; + } + case 2: { + toScale = scale; + to = new ToY(); + break; + } + case 3: + to = new ToScaleX(); + break; + case 4: + to = new ToScaleY(); + break; + case 5: + to = new ToShearY(); + break; + default: + to = null; + } + if (!to) continue; + to.offset = input.readFloat() * toScale; + to.max = input.readFloat() * toScale; + to.scale = input.readFloat() * toScale / fromScale; + from.to[t] = to; + } + data.properties[ii] = from; + } + flags = input.readByte(); + if ((flags & 1) !== 0) data.offsets[TransformConstraintData.ROTATION] = input.readFloat(); + if ((flags & 2) !== 0) data.offsets[TransformConstraintData.X] = input.readFloat() * scale; + if ((flags & 4) !== 0) data.offsets[TransformConstraintData.Y] = input.readFloat() * scale; + if ((flags & 8) !== 0) data.offsets[TransformConstraintData.SCALEX] = input.readFloat(); + if ((flags & 16) !== 0) data.offsets[TransformConstraintData.SCALEY] = input.readFloat(); + if ((flags & 32) !== 0) data.offsets[TransformConstraintData.SHEARY] = input.readFloat(); + flags = input.readByte(); + const setup = data.setupPose; + if ((flags & 1) !== 0) setup.mixRotate = input.readFloat(); + if ((flags & 2) !== 0) setup.mixX = input.readFloat(); + if ((flags & 4) !== 0) setup.mixY = input.readFloat(); + if ((flags & 8) !== 0) setup.mixScaleX = input.readFloat(); + if ((flags & 16) !== 0) setup.mixScaleY = input.readFloat(); + if ((flags & 32) !== 0) setup.mixShearY = input.readFloat(); + constraints.push(data); + break; + } + case CONSTRAINT_PATH: { + const data = new PathConstraintData(name); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(bones[input.readInt(true)]); + data.slot = skeletonData.slots[input.readInt(true)]; + const flags = input.readByte(); + data.skinRequired = (flags & 1) !== 0; + data.positionMode = flags >> 1 & 1; + data.spacingMode = flags >> 2 & 3; + data.rotateMode = flags >> 4 & 3; + if ((flags & 128) !== 0) data.offsetRotation = input.readFloat(); + const setup = data.setupPose; + setup.position = input.readFloat(); + if (data.positionMode === 0 /* Fixed */) setup.position *= scale; + setup.spacing = input.readFloat(); + if (data.spacingMode === 0 /* Length */ || data.spacingMode === 1 /* Fixed */) setup.spacing *= scale; + setup.mixRotate = input.readFloat(); + setup.mixX = input.readFloat(); + setup.mixY = input.readFloat(); + constraints.push(data); + break; + } + case CONSTRAINT_PHYSICS: { + const data = new PhysicsConstraintData(name); + data.bone = bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) !== 0; + if ((flags & 2) !== 0) data.x = input.readFloat(); + if ((flags & 4) !== 0) data.y = input.readFloat(); + if ((flags & 8) !== 0) data.rotate = input.readFloat(); + if ((flags & 16) !== 0) { + let scaleX = input.readFloat(); + if (scaleX < -2) { + data.scaleYMode = 2 /* Volume */; + scaleX = -2 - scaleX; + } else if (scaleX < 0) { + data.scaleYMode = 1 /* Uniform */; + scaleX = -1 - scaleX; + } + data.scaleX = scaleX; + } + if ((flags & 32) !== 0) data.shearX = input.readFloat(); + data.limit = ((flags & 64) !== 0 ? input.readFloat() : 5e3) * scale; + data.step = 1 / input.readUnsignedByte(); + const setup = data.setupPose; + setup.inertia = input.readFloat(); + setup.strength = input.readFloat(); + setup.damping = input.readFloat(); + setup.massInverse = (flags & 128) !== 0 ? input.readFloat() : 1; + setup.wind = input.readFloat(); + setup.gravity = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) !== 0) data.inertiaGlobal = true; + if ((flags & 2) !== 0) data.strengthGlobal = true; + if ((flags & 4) !== 0) data.dampingGlobal = true; + if ((flags & 8) !== 0) data.massGlobal = true; + if ((flags & 16) !== 0) data.windGlobal = true; + if ((flags & 32) !== 0) data.gravityGlobal = true; + if ((flags & 64) !== 0) data.mixGlobal = true; + setup.mix = (flags & 128) !== 0 ? input.readFloat() : 1; + constraints.push(data); + break; + } + case CONSTRAINT_SLIDER: { + const data = new SliderData(name); + const flags = input.readByte(); + data.skinRequired = (flags & 1) !== 0; + data.loop = (flags & 2) !== 0; + data.additive = (flags & 4) !== 0; + if ((flags & 8) !== 0) { + const value = input.readFloat(); + if (nonessential && (flags & 64) !== 0) + data.max = value; + else + data.setupPose.time = value; + } + if ((flags & 16) !== 0) data.setupPose.mix = (flags & 32) !== 0 ? input.readFloat() : 1; + if ((flags & 64) !== 0) { + data.local = (flags & 128) !== 0; + data.bone = bones[input.readInt(true)]; + const offset = input.readFloat(); + let propertyScale = 1; + switch (input.readByte()) { + case 0: + data.property = new FromRotate(); + break; + case 1: { + propertyScale = scale; + data.property = new FromX(); + break; + } + case 2: { + propertyScale = scale; + data.property = new FromY(); + break; + } + case 3: + data.property = new FromScaleX(); + break; + case 4: + data.property = new FromScaleY(); + break; + case 5: + data.property = new FromShearY(); + break; + default: + continue; + } + ; + data.property.offset = offset * propertyScale; + data.offset = input.readFloat(); + data.scale = input.readFloat() / propertyScale; + } + constraints.push(data); + break; + } + } + } + const defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) { + const skin = this.readSkin(input, skeletonData, false, nonessential); + if (!skin) throw new Error("readSkin() should not have returned null."); + skeletonData.skins[i] = skin; + } + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + const linkedMesh = this.linkedMeshes[i]; + const skin = skeletonData.skins[linkedMesh.skinIndex]; + if (!linkedMesh.source) throw new Error("Linked mesh parent must not be null"); + const source = skin.getAttachment(linkedMesh.sourceIndex, linkedMesh.source); + if (!source) throw new Error(`Source mesh not found: ${linkedMesh.source}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimelines ? source : linkedMesh.mesh; + linkedMesh.mesh.setSourceMesh(source); + linkedMesh.mesh.updateSequence(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + const eventName = input.readString(); + if (!eventName) throw new Error("Event data name must not be null"); + const data = new EventData(eventName); + const setup = data.setupPose; + setup.intValue = input.readInt(false); + setup.floatValue = input.readFloat(); + setup.stringValue = input.readString(); + data._audioPath = input.readString(); + if (data.audioPath) { + setup.volume = input.readFloat(); + setup.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + const animations = skeletonData.animations; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + const animationName = input.readString(); + if (!animationName) throw new Error("Animation name must not be null."); + animations.push(this.readAnimation(input, animationName, skeletonData, nonessential)); + } + for (let i = 0; i < constraintCount; i++) { + const constraint = constraints[i]; + if (constraint instanceof SliderData) constraint.animation = animations[input.readInt(true)]; + } + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount === 0) return null; + skin = new Skin("default"); + } else { + const skinName = input.readString(); + if (!skinName) throw new Error("Skin name must not be null."); + skin = new Skin(skinName); + if (nonessential) Color.rgba8888ToColor(skin.color, input.readInt32()); + let n = input.readInt(true); + let from = skeletonData.bones, to = skin.bones; + for (let i = 0; i < n; i++) + to[i] = from[input.readInt(true)]; + n = input.readInt(true); + from = skeletonData.constraints; + to = skin.constraints; + for (let i = 0; i < n; i++) + to[i] = from[input.readInt(true)]; + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + const slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const placeholder = input.readStringRef(); + if (!placeholder) + throw new Error("Attachment name must not be null"); + const attachment = this.readAttachment(input, skeletonData, skin, slotIndex, placeholder, nonessential); + if (attachment) skin.setAttachment(slotIndex, placeholder, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, placeholder, nonessential) { + const scale = this.scale; + const flags = input.readByte(); + const name = (flags & 8) !== 0 ? input.readStringRef() : placeholder; + if (!name) throw new Error("Attachment name must not be null"); + switch (flags & 7) { + // BUG? + case 0 /* Region */: { + let path = (flags & 16) !== 0 ? input.readStringRef() : null; + const color = (flags & 32) !== 0 ? input.readInt32() : 4294967295; + const sequence = this.readSequence(input, (flags & 64) !== 0); + const rotation = (flags & 128) !== 0 ? input.readFloat() : 0; + const x = input.readFloat(); + const y = input.readFloat(); + const scaleX = input.readFloat(); + const scaleY = input.readFloat(); + const width = input.readFloat(); + const height = input.readFloat(); + if (!path) path = name; + const region = this.attachmentLoader.newRegionAttachment(skin, placeholder, name, path, sequence); + if (!region) return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.updateSequence(); + return region; + } + case 1 /* BoundingBox */: { + const vertices = this.readVertices(input, (flags & 16) !== 0); + const color = nonessential ? input.readInt32() : 0; + const box = this.attachmentLoader.newBoundingBoxAttachment(skin, placeholder, name); + if (!box) return null; + box.worldVerticesLength = vertices.length; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) Color.rgba8888ToColor(box.color, color); + return box; + } + case 2 /* Mesh */: { + let path = (flags & 16) !== 0 ? input.readStringRef() : name; + const color = (flags & 32) !== 0 ? input.readInt32() : 4294967295; + const sequence = this.readSequence(input, (flags & 64) !== 0); + const hullLength = input.readInt(true); + const vertices = this.readVertices(input, (flags & 128) !== 0); + const uvs = this.readFloatArray(input, vertices.length, 1); + const triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3); + const slotCount = input.readInt(true); + let timelineSlots = null; + if (slotCount > 0) { + timelineSlots = []; + for (let i = 0; i < slotCount; i++) + timelineSlots[i] = input.readInt(true); + } + let edges = []; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input, input.readInt(true)); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) path = name; + const mesh = this.attachmentLoader.newMeshAttachment(skin, placeholder, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.hullLength = hullLength << 1; + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertices.length; + mesh.regionUVs = uvs; + mesh.triangles = triangles; + if (timelineSlots) mesh.timelineSlots = timelineSlots; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + mesh.updateSequence(); + return mesh; + } + case 3 /* LinkedMesh */: { + const path = (flags & 16) !== 0 ? input.readStringRef() : name; + if (path == null) throw new Error("Path of linked mesh must not be null"); + const color = (flags & 32) !== 0 ? input.readInt32() : 4294967295; + const sequence = this.readSequence(input, (flags & 64) !== 0); + const inheritTimelines = (flags & 128) !== 0; + const sourceIndex = input.readInt(true); + const skinIndex = input.readInt(true); + const source = input.readStringRef(); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + const mesh = this.attachmentLoader.newMeshAttachment(skin, placeholder, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, sourceIndex, source, inheritTimelines)); + return mesh; + } + case 4 /* Path */: { + const closed = (flags & 16) !== 0; + const constantSpeed = (flags & 32) !== 0; + const vertices = this.readVertices(input, (flags & 64) !== 0); + const lengths = this.readFloatArray(input, vertices.length / 6, scale); + const color = nonessential ? input.readInt32() : 0; + const path = this.attachmentLoader.newPathAttachment(skin, placeholder, name); + if (!path) return null; + path.closed = closed; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertices.length; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) Color.rgba8888ToColor(path.color, color); + return path; + } + case 5 /* Point */: { + const rotation = input.readFloat(); + const x = input.readFloat(); + const y = input.readFloat(); + const color = nonessential ? input.readInt32() : 0; + const point = this.attachmentLoader.newPointAttachment(skin, placeholder, name); + if (!point) return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) Color.rgba8888ToColor(point.color, color); + return point; + } + case 6 /* Clipping */: { + const endSlotIndex = input.readInt(true); + const vertices = this.readVertices(input, (flags & 16) !== 0); + const color = nonessential ? input.readInt32() : 0; + const clip = this.attachmentLoader.newClippingAttachment(skin, placeholder, name); + if (!clip) return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.convex = (flags & 32) !== 0; + clip.inverse = (flags & 64) !== 0; + clip.worldVerticesLength = vertices.length; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + } + readSequence(input, hasPathSuffix) { + if (!hasPathSuffix) return new Sequence(1, false); + const sequence = new Sequence(input.readInt(true), true); + sequence.start = input.readInt(true); + sequence.digits = input.readInt(true); + sequence.setupIndex = input.readInt(true); + return sequence; + } + readVertices(input, weighted) { + const scale = this.scale; + const vertexCount = input.readInt(true); + const length = vertexCount << 1; + if (!weighted) + return new Vertices(null, this.readFloatArray(input, length, scale), length); + const n = input.readInt(true); + const bones = []; + const weights = []; + for (let b = 0, w = 0; b < n; ) { + const boneCount = input.readInt(true); + bones[b++] = boneCount; + for (let ii = 0; ii < boneCount; ii++, w += 3) { + bones[b++] = input.readInt(true); + weights[w] = input.readFloat() * scale; + weights[w + 1] = input.readFloat() * scale; + weights[w + 2] = input.readFloat(); + } + } + return new Vertices(bones, Utils.toFloatArray(weights), length); + } + readFloatArray(input, n, scale) { + const array = []; + if (scale === 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input, n) { + const array = []; + for (let i = 0; i < n; i++) + array[i] = input.readInt(true); + return array; + } + readAnimation(input, name, skeletonData, nonessential) { + input.readInt(true); + const timelines = []; + const scale = this.scale; + for (let i = 0, n = input.readInt(true); i < n; i++) { + const slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const timelineType = input.readByte(); + const frameCount = input.readInt(true); + const frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + const timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + const bezierCount = input.readInt(true); + const timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame === frameLast) break; + const time2 = input.readFloat(); + const r2 = input.readUnsignedByte() / 255; + const g2 = input.readUnsignedByte() / 255; + const b2 = input.readUnsignedByte() / 255; + const a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + const bezierCount = input.readInt(true); + const timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame === frameLast) break; + const time2 = input.readFloat(); + const r2 = input.readUnsignedByte() / 255; + const g2 = input.readUnsignedByte() / 255; + const b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + const bezierCount = input.readInt(true); + const timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame === frameLast) break; + const time2 = input.readFloat(); + const nr = input.readUnsignedByte() / 255; + const ng = input.readUnsignedByte() / 255; + const nb = input.readUnsignedByte() / 255; + const na = input.readUnsignedByte() / 255; + const nr2 = input.readUnsignedByte() / 255; + const ng2 = input.readUnsignedByte() / 255; + const nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + const bezierCount = input.readInt(true); + const timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame === frameLast) break; + const time2 = input.readFloat(); + const nr = input.readUnsignedByte() / 255; + const ng = input.readUnsignedByte() / 255; + const nb = input.readUnsignedByte() / 255; + const nr2 = input.readUnsignedByte() / 255; + const ng2 = input.readUnsignedByte() / 255; + const nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + const timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame === frameLast) break; + const time2 = input.readFloat(); + const a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true); + if (type === BONE_INHERIT) { + const timeline = new InheritTimeline(frameCount, boneIndex); + for (let frame = 0; frame < frameCount; frame++) { + timeline.setFrame(frame, input.readFloat(), input.readByte()); + } + timelines.push(timeline); + continue; + } + const bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + readTimeline(input, timelines, new RotateTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_TRANSLATE: + readTimeline(input, timelines, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEX: + readTimeline(input, timelines, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_TRANSLATEY: + readTimeline(input, timelines, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale); + break; + case BONE_SCALE: + readTimeline(input, timelines, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_SCALEX: + readTimeline(input, timelines, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_SCALEY: + readTimeline(input, timelines, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_SHEAR: + readTimeline(input, timelines, new ShearTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_SHEARX: + readTimeline(input, timelines, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1); + break; + case BONE_SHEARY: + readTimeline(input, timelines, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1); + break; + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + const timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let flags = input.readByte(); + let time = input.readFloat(), mix = (flags & 1) !== 0 ? (flags & 2) !== 0 ? input.readFloat() : 1 : 0; + let softness = (flags & 4) !== 0 ? input.readFloat() * scale : 0; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, (flags & 8) !== 0 ? 1 : -1, (flags & 16) !== 0, (flags & 32) !== 0); + if (frame === frameLast) break; + flags = input.readByte(); + const time2 = input.readFloat(), mix2 = (flags & 1) !== 0 ? (flags & 2) !== 0 ? input.readFloat() : 1 : 0; + const softness2 = (flags & 4) !== 0 ? input.readFloat() * scale : 0; + if ((flags & 64) !== 0) { + timeline.setStepped(frame); + } else if ((flags & 128) !== 0) { + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + const timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame === frameLast) break; + const time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true); + const data = skeletonData.constraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case PATH_POSITION: + readTimeline( + input, + timelines, + new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data.positionMode === 0 /* Fixed */ ? scale : 1 + ); + break; + case PATH_SPACING: + readTimeline( + input, + timelines, + new PathConstraintSpacingTimeline(frameCount, bezierCount, index), + data.spacingMode === 0 /* Length */ || data.spacingMode === 1 /* Fixed */ ? scale : 1 + ); + break; + case PATH_MIX: { + const timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame === frameLast) break; + const time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true) - 1; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true); + if (type === PHYSICS_RESET) { + const timeline = new PhysicsConstraintResetTimeline(frameCount, index); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat()); + timelines.push(timeline); + continue; + } + const bezierCount = input.readInt(true); + switch (type) { + case PHYSICS_INERTIA: + readTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_STRENGTH: + readTimeline(input, timelines, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_DAMPING: + readTimeline(input, timelines, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_MASS: + readTimeline(input, timelines, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_WIND: + readTimeline(input, timelines, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_GRAVITY: + readTimeline(input, timelines, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1); + break; + case PHYSICS_MIX: + readTimeline(input, timelines, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1); + break; + default: + throw new Error("Unknown physics timeline type."); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case SLIDER_TIME: + readTimeline(input, timelines, new SliderTimeline(frameCount, bezierCount, index), 1); + break; + case SLIDER_MIX: + readTimeline(input, timelines, new SliderMixTimeline(frameCount, bezierCount, index), 1); + break; + default: + throw new Error(`Uknown slider type: ${type}`); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + const attachmentName = input.readStringRef(); + if (!attachmentName) throw new Error("attachmentName must not be null."); + const attachment = skin.getAttachment(slotIndex, attachmentName); + const timelineType = input.readByte(); + const frameCount = input.readInt(true); + const frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + const vertexAttachment = attachment; + const weighted = vertexAttachment.bones; + const vertices = vertexAttachment.vertices; + const deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + const bezierCount = input.readInt(true); + const timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end === 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + const start = input.readInt(true); + end += start; + if (scale === 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame === frameLast) break; + const time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + const timeline = new SequenceTimeline(frameCount, slotIndex, attachment); + for (let frame = 0; frame < frameCount; frame++) { + const time = input.readFloat(); + const modeAndIndex = input.readInt32(); + timeline.setFrame( + frame, + time, + SequenceModeValues[modeAndIndex & 15], + modeAndIndex >> 4, + input.readFloat() + ); + } + timelines.push(timeline); + break; + } + } + } + } + } + const slotCount = skeletonData.slots.length; + const drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + const timeline = new DrawOrderTimeline(drawOrderCount); + for (let i = 0; i < drawOrderCount; i++) + timeline.setFrame(i, input.readFloat(), readDrawOrder(input, slotCount)); + timelines.push(timeline); + } + const folderCount = input.readInt(true); + for (let i = 0; i < folderCount; i++) { + const folderSlotCount = input.readInt(true); + const folderSlots = new Array(folderSlotCount); + for (let ii = 0; ii < folderSlotCount; ii++) + folderSlots[ii] = input.readInt(true); + const keyCount = input.readInt(true); + const timeline = new DrawOrderFolderTimeline(keyCount, folderSlots, slotCount); + for (let ii = 0; ii < keyCount; ii++) + timeline.setFrame(ii, input.readFloat(), readDrawOrder(input, folderSlotCount)); + timelines.push(timeline); + } + const eventCount = input.readInt(true); + if (eventCount > 0) { + const timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + const time = input.readFloat(); + const eventData = skeletonData.events[input.readInt(true)]; + const event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readString(); + if (event.stringValue == null) event.stringValue = eventData.setupPose.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + const animation = new Animation(name, timelines, duration); + if (nonessential) Color.rgba8888ToColor(animation.color, input.readInt32()); + return animation; + } + }; + var BinaryInput = class { + constructor(data, strings = [], index = 0, buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + const value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + const value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) !== 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) !== 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) !== 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) !== 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + const index = this.readInt(true); + return index === 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + for (let i = 0; i < byteCount; ) { + const b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + const value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() !== 0; + } + }; + var LinkedMesh = class { + source; + skinIndex; + slotIndex; + sourceIndex; + mesh; + inheritTimelines; + constructor(mesh, skinIndex, slotIndex, sourceIndex, source, inheritTimelines) { + this.mesh = mesh; + this.skinIndex = skinIndex; + this.slotIndex = slotIndex; + this.sourceIndex = sourceIndex; + this.source = source; + this.inheritTimelines = inheritTimelines; + } + }; + var Vertices = class { + constructor(bones = null, vertices, length = 0) { + this.bones = bones; + this.vertices = vertices; + this.length = length; + } + }; + function readTimeline(input, timelines, timeline, scale) { + if (timeline instanceof CurveTimeline1) + readTimeline1(input, timelines, timeline, scale); + else + readTimeline2(input, timelines, timeline, scale); + } + function readTimeline1(input, timelines, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame === frameLast) break; + const time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + timelines.push(timeline); + } + function readTimeline2(input, timelines, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame === frameLast) break; + const time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + timelines.push(timeline); + } + function readDrawOrder(input, slotCount) { + const changeCount = input.readInt(true); + if (changeCount === 0) return null; + const drawOrder = new Array(slotCount).fill(-1); + const unchanged = new Array(slotCount - changeCount); + let originalIndex = 0, unchangedIndex = 0; + for (let i = 0; i < changeCount; i++) { + const slotIndex = input.readInt(true); + while (originalIndex !== slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] === -1) drawOrder[i] = unchanged[--unchangedIndex]; + return drawOrder; + } + function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); + } + var BONE_ROTATE = 0; + var BONE_TRANSLATE = 1; + var BONE_TRANSLATEX = 2; + var BONE_TRANSLATEY = 3; + var BONE_SCALE = 4; + var BONE_SCALEX = 5; + var BONE_SCALEY = 6; + var BONE_SHEAR = 7; + var BONE_SHEARX = 8; + var BONE_SHEARY = 9; + var BONE_INHERIT = 10; + var SLOT_ATTACHMENT = 0; + var SLOT_RGBA = 1; + var SLOT_RGB = 2; + var SLOT_RGBA2 = 3; + var SLOT_RGB2 = 4; + var SLOT_ALPHA = 5; + var CONSTRAINT_IK = 0; + var CONSTRAINT_PATH = 1; + var CONSTRAINT_TRANSFORM = 2; + var CONSTRAINT_PHYSICS = 3; + var CONSTRAINT_SLIDER = 4; + var ATTACHMENT_DEFORM = 0; + var ATTACHMENT_SEQUENCE = 1; + var PATH_POSITION = 0; + var PATH_SPACING = 1; + var PATH_MIX = 2; + var PHYSICS_INERTIA = 0; + var PHYSICS_STRENGTH = 1; + var PHYSICS_DAMPING = 2; + var PHYSICS_MASS = 4; + var PHYSICS_WIND = 5; + var PHYSICS_GRAVITY = 6; + var PHYSICS_MIX = 7; + var PHYSICS_RESET = 8; + var SLIDER_TIME = 0; + var SLIDER_MIX = 1; + var CURVE_STEPPED = 1; + var CURVE_BEZIER = 2; + + // spine-core/src/SkeletonBounds.ts + var SkeletonBounds = class { + /** The left edge of the axis aligned bounding box. */ + minX = 0; + /** The bottom edge of the axis aligned bounding box. */ + minY = 0; + /** The right edge of the axis aligned bounding box. */ + maxX = 0; + /** The top edge of the axis aligned bounding box. */ + maxY = 0; + /** The visible bounding boxes. */ + boundingBoxes = []; + /** The world vertices for the bounding box polygons. */ + polygons = []; + polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + /** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding + * box's polygon. + * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the + * SkeletonBounds AABB methods will always return true. */ + update(skeleton, updateAabb) { + if (!skeleton) throw new Error("skeleton cannot be null."); + const boundingBoxes = this.boundingBoxes; + const polygons = this.polygons; + const polygonPool = this.polygonPool; + const slots = skeleton.slots; + const slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + const slot = slots[i]; + if (!slot.bone.active) continue; + const attachment = slot.appliedPose.attachment; + if (attachment instanceof BoundingBoxAttachment) { + boundingBoxes.push(attachment); + let polygon = polygonPool.obtain(); + if (polygon.length !== attachment.worldVerticesLength) { + polygon = Utils.newFloatArray(attachment.worldVerticesLength); + } + polygons.push(polygon); + attachment.computeWorldVertices(skeleton, slot, 0, attachment.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + const polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + const polygon = polygons[i]; + const vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + const x = vertices[ii]; + const y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + /** Returns true if the axis aligned bounding box contains the point. */ + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + /** Returns true if the axis aligned bounding box intersects the line segment. */ + aabbIntersectsSegment(x1, y1, x2, y2) { + const minX = this.minX; + const minY = this.minY; + const maxX = this.maxX; + const maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + const m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) return true; + return false; + } + /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + * efficient to only call this method if {@link aabbContainsPoint} returns true. */ + containsPoint(x, y) { + const polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains the point. */ + containsPointPolygon(polygon, x, y) { + const vertices = polygon; + const nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + const vertexY = vertices[ii + 1]; + const prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + const vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside; + } + prevIndex = ii; + } + return inside; + } + /** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + * is usually more efficient to only call this method if {@link aabbIntersectsSegment} returns + * true. */ + intersectsSegment(x1, y1, x2, y2) { + const polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains any part of the line segment. */ + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + const vertices = polygon; + const nn = polygon.length; + const width12 = x1 - x2, height12 = y1 - y2; + const det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + const x4 = vertices[ii], y4 = vertices[ii + 1]; + const det2 = x3 * y4 - y3 * x4; + const width34 = x3 - x4, height34 = y3 - y4; + const det3 = width12 * height34 - height12 * width34; + const x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + const y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + /** Returns the polygon for the specified bounding box, or null. */ + getPolygon(boundingBox) { + if (!boundingBox) throw new Error("boundingBox cannot be null."); + const index = this.boundingBoxes.indexOf(boundingBox); + return index === -1 ? null : this.polygons[index]; + } + /** The width of the axis aligned bounding box. */ + getWidth() { + return this.maxX - this.minX; + } + /** The height of the axis aligned bounding box. */ + getHeight() { + return this.maxY - this.minY; + } + }; + + // spine-core/src/Triangulator.ts + var Triangulator = class _Triangulator { + convexPolygons = []; + convexPolygonsIndices = []; + indicesArray = []; + isConcaveArray = []; + triangles = []; + polygonPool = new Pool(() => { + return []; + }); + polygonIndicesPool = new Pool(() => { + return []; + }); + triangulate(verticesArray) { + const vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + const indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + const isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0; i < vertexCount; i++) + isConcave[i] = _Triangulator.isConcave(i, vertexCount, vertices, indices); + const triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + const p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + const p1x = vertices[p1], p1y = vertices[p1 + 1]; + const p2x = vertices[p2], p2y = vertices[p2 + 1]; + const p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = next + 1 < vertexCount ? next + 1 : 0; ii !== previous; ) { + if (isConcave[ii]) { + const v = indices[ii] << 1; + const vx = vertices[v], vy = vertices[v + 1]; + if (_Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy) && _Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy) && _Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer; + } + if (++ii === vertexCount) ii = 0; + } + break; + } + if (next === 0) { + do { + if (!isConcave[i]) break; + i--; + } while (i > 0); + previous = i > 0 ? i - 1 : vertexCount - 1; + next = i + 1 < vertexCount ? i + 1 : 0; + break; + } + previous = i; + i = next; + if (++next === vertexCount) next = 0; + } + triangles.push(indices[previous], indices[i], indices[next]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + const previousIndex = i > 0 ? i - 1 : vertexCount - 1; + const nextIndex = i < vertexCount ? i : 0; + isConcave[previousIndex] = _Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = _Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount === 3) triangles.push(indices[2], indices[0], indices[1]); + return triangles; + } + decompose(verticesArray, triangles) { + const vertices = verticesArray; + const convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + const convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + const t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + const x1 = vertices[t1], y1 = vertices[t1 + 1]; + const x2 = vertices[t2], y2 = vertices[t2 + 1]; + const x3 = vertices[t3], y3 = vertices[t3 + 1]; + if (fanBaseIndex === t1) { + const o = polygon.length - 4; + if (_Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3) === lastWinding && _Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]) === lastWinding) { + polygon.push(x3, y3); + polygonIndices.push(t3); + continue; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + polygon = this.polygonPool.obtain(); + polygonIndices = this.polygonIndicesPool.obtain(); + } + polygon.length = 0; + polygon.push(x1, y1, x2, y2); + polygon.push(x3, y3); + polygonIndices.length = 0; + polygonIndices.push(t1, t2, t3); + lastWinding = _Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length === 0) continue; + const firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + const o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + const firstX = polygon[0], firstY = polygon[1]; + const secondX = polygon[2], secondY = polygon[3]; + const winding = _Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii === i) continue; + const otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length !== 3) continue; + const otherFirstIndex = otherIndices[0]; + const otherSecondIndex = otherIndices[1]; + const otherLastIndex = otherIndices[2]; + const otherPoly = convexPolygons[ii]; + const x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex !== firstIndex || otherSecondIndex !== lastIndex) continue; + if (_Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3) === winding && _Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY) === winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3, y3); + polygonIndices.push(otherLastIndex); + lastIndex = otherLastIndex; + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = -1; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length === 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } else + polygon.push(polygon[0], polygon[1]); + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + const previous = indices[index > 0 ? index - 1 : vertexCount - 1] << 1; + const current = indices[index] << 1; + const next = indices[index + 1 < vertexCount ? index + 1 : 0] << 1; + return !_Triangulator.positiveArea( + vertices[previous], + vertices[previous + 1], + vertices[current], + vertices[current + 1], + vertices[next], + vertices[next + 1] + ); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0 ? 1 : -1; + } + }; + + // spine-core/src/SkeletonClipping.ts + var SkeletonClipping = class { + triangulator = null; + clippingPolygon = []; + clippingPolygons = []; + clipOutput = []; + clippedVertices = []; + /** An empty array unless {@link clipTrianglesUnpacked} was used. **/ + clippedUVs = []; + clippedTriangles = []; + inverseVertices = []; + _clippedVerticesTyped = new Float32Array(1024); + _clippedUVsTyped = new Float32Array(1024); + _clippedTrianglesTyped = new Uint16Array(1024); + clippedVerticesTyped = new Float32Array(0); + clippedUVsTyped = new Float32Array(0); + clippedTrianglesTyped = new Uint16Array(0); + clippedVerticesLength = 0; + clippedUVsLength = 0; + clippedTrianglesLength = 0; + scratch = []; + inverse = false; + clipAttachment = null; + clipStart(skeleton, slot, clip) { + if (this.clipAttachment) return; + const n = clip.worldVerticesLength; + this.clipAttachment = clip; + this.inverse = clip.inverse; + const vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(skeleton, slot, 0, n, vertices, 0, 2); + const clippingPolygon = this.clippingPolygon; + const convex = this.makeClockwise(clippingPolygon); + if (convex || this.inverse || clip.convex) { + if (!convex) this.makeConvex(clippingPolygon); + this.clippingPolygon.push(clippingPolygon[0], clippingPolygon[1]); + this.clippingPolygons.push(clippingPolygon); + } else { + if (this.triangulator === null) this.triangulator = new Triangulator(); + this.clippingPolygons.push(...this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon))); + } + } + clipEnd(slot) { + if (!this.clipAttachment) return; + if (slot && this.clipAttachment.endSlot !== slot.data) return; + this.clipAttachment = null; + this.clippingPolygons.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, triangles, trianglesLength, uvs, light, dark, twoColor, stride) { + return uvs && light && dark && typeof twoColor === "boolean" && typeof stride === "number" ? this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor, stride) : this.clipTrianglesNoRender(vertices, triangles, trianglesLength); + } + clipTrianglesNoRender(vertices, triangles, trianglesLength) { + const clippedVertices = this.clippedVertices; + clippedVertices.length = 0; + const clippedTriangles = this.clippedTriangles; + clippedTriangles.length = 0; + let index = 0; + if (this.inverse) { + const polygon = this.clippingPolygons[0]; + for (let i = 0; i < trianglesLength; i += 3) { + let t = triangles[i] << 1; + const x1 = vertices[t], y1 = vertices[t + 1]; + t = triangles[i + 1] << 1; + const x2 = vertices[t], y2 = vertices[t + 1]; + t = triangles[i + 2] << 1; + const x3 = vertices[t], y3 = vertices[t + 1]; + this.clipInverse(x1, y1, x2, y2, x3, y3, polygon); + const iv = this.inverseVertices; + for (let offset = 0, nn = this.inverseVertices.length; offset < nn; ) { + const polygonSize = iv[offset++]; + let vertexCount = polygonSize >> 1, s = clippedVertices.length; + const cv = Utils.setArraySize(clippedVertices, s + polygonSize); + Utils.arrayCopy(iv, offset, cv, s, polygonSize); + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3 * (vertexCount - 2)); + for (let ii = 1; ii < vertexCount - 1; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += vertexCount; + offset += polygonSize; + } + } + return true; + } + const clipOutput = this.clipOutput; + const polygons = this.clippingPolygons; + const polygonsCount = polygons.length; + let clipOutputItems = null; + for (let i = 0; i < trianglesLength; i += 3) { + let t = triangles[i] << 1; + const x1 = vertices[t], y1 = vertices[t + 1]; + t = triangles[i + 1] << 1; + const x2 = vertices[t], y2 = vertices[t + 1]; + t = triangles[i + 2] << 1; + const x3 = vertices[t], y3 = vertices[t + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p])) { + clipOutputItems = this.clipOutput; + const clipOutputLength = clipOutput.length; + if (clipOutputLength === 0) continue; + let clipOutputCount = clipOutputLength >> 1; + const cv = Utils.setArraySize(clippedVertices, s + clipOutputLength); + Utils.arrayCopy(clipOutputItems, 0, cv, s, clipOutputLength); + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += clipOutputCount; + } else { + const cv = Utils.setArraySize(clippedVertices, s + 3 * 2); + cv[s] = x1; + cv[s + 1] = y1; + cv[s + 2] = x2; + cv[s + 3] = y2; + cv[s + 4] = x3; + cv[s + 5] = y3; + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3); + ct[s] = index; + ct[s + 1] = index + 1; + ct[s + 2] = index + 2; + index += 3; + break; + } + } + } + return clipOutputItems != null; + } + clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor, stride) { + const clippedVertices = this.clippedVertices; + clippedVertices.length = 0; + const clippedTriangles = this.clippedTriangles; + clippedTriangles.length = 0; + let index = 0; + if (this.inverse) { + const polygon = this.clippingPolygons[0]; + for (let i = 0; i < trianglesLength; i += 3) { + let t0 = triangles[i], t1 = triangles[i + 1], t2 = triangles[i + 2]; + const x1 = vertices[t0 * stride], y1 = vertices[t0 * stride + 1]; + const x2 = vertices[t1 * stride], y2 = vertices[t1 * stride + 1]; + const x3 = vertices[t2 * stride], y3 = vertices[t2 * stride + 1]; + this.clipInverse(x1, y1, x2, y2, x3, y3, polygon); + const nn = this.inverseVertices.length; + if (nn === 0) continue; + const u1 = uvs[t0 <<= 1], v1 = uvs[t0 + 1]; + const u2 = uvs[t1 <<= 1], v2 = uvs[t1 + 1]; + const u3 = uvs[t2 <<= 1], v3 = uvs[t2 + 1]; + const d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1, d = 1 / (d0 * d2 + d1 * (y1 - y3)); + const iv = this.inverseVertices; + for (let offset = 0; offset < nn; ) { + const polygonSize = iv[offset++]; + const vertexCount = polygonSize >> 1; + let s = clippedVertices.length; + const cv = Utils.setArraySize(clippedVertices, s + vertexCount * stride); + for (let ii = 0; ii < polygonSize; ii += 2, s += stride) { + const x = iv[offset + ii], y = iv[offset + ii + 1]; + cv[s] = x; + cv[s + 1] = y; + cv[s + 2] = light.r; + cv[s + 3] = light.g; + cv[s + 4] = light.b; + cv[s + 5] = light.a; + const c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cv[s + 6] = u1 * a + u2 * b + u3 * c; + cv[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + cv[s + 8] = dark.r; + cv[s + 9] = dark.g; + cv[s + 10] = dark.b; + cv[s + 11] = dark.a; + } + } + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3 * (vertexCount - 2)); + for (let ii = 1; ii < vertexCount - 1; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += vertexCount; + offset += polygonSize; + } + } + return true; + } + const clipOutput = this.clipOutput; + const polygons = this.clippingPolygons; + const polygonsCount = this.clippingPolygons.length; + let clipOutputItems = null; + for (let i = 0; i < trianglesLength; i += 3) { + let t = triangles[i]; + const x1 = vertices[t * stride], y1 = vertices[t * stride + 1]; + const u1 = uvs[t << 1], v1 = uvs[(t << 1) + 1]; + t = triangles[i + 1]; + const x2 = vertices[t * stride], y2 = vertices[t * stride + 1]; + const u2 = uvs[t << 1], v2 = uvs[(t << 1) + 1]; + t = triangles[i + 2]; + const x3 = vertices[t * stride], y3 = vertices[t * stride + 1]; + const u3 = uvs[t << 1], v3 = uvs[(t << 1) + 1]; + let d0 = 0, d1 = 0, d2 = 0, d4 = 0, d = 0; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p])) { + clipOutputItems = this.clipOutput; + const clipOutputLength = clipOutput.length; + if (clipOutputLength === 0) continue; + let clipOutputCount = clipOutputLength >> 1; + if (d === 0) { + d0 = y2 - y3; + d1 = x3 - x2; + d2 = x1 - x3; + d4 = y3 - y1; + d = 1 / (d0 * d2 - d1 * d4); + } + const cv = Utils.setArraySize(clippedVertices, s + clipOutputCount * stride); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += stride) { + const x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + cv[s] = x; + cv[s + 1] = y; + cv[s + 2] = light.r; + cv[s + 3] = light.g; + cv[s + 4] = light.b; + cv[s + 5] = light.a; + const c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cv[s + 6] = u1 * a + u2 * b + u3 * c; + cv[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + cv[s + 8] = dark.r; + cv[s + 9] = dark.g; + cv[s + 10] = dark.b; + cv[s + 11] = dark.a; + } + } + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + const cv = Utils.setArraySize(clippedVertices, s + 3 * stride); + cv[s] = x1; + cv[s + 1] = y1; + cv[s + 2] = light.r; + cv[s + 3] = light.g; + cv[s + 4] = light.b; + cv[s + 5] = light.a; + if (!twoColor) { + cv[s + 6] = u1; + cv[s + 7] = v1; + cv[s + 8] = x2; + cv[s + 9] = y2; + cv[s + 10] = light.r; + cv[s + 11] = light.g; + cv[s + 12] = light.b; + cv[s + 13] = light.a; + cv[s + 14] = u2; + cv[s + 15] = v2; + cv[s + 16] = x3; + cv[s + 17] = y3; + cv[s + 18] = light.r; + cv[s + 19] = light.g; + cv[s + 20] = light.b; + cv[s + 21] = light.a; + cv[s + 22] = u3; + cv[s + 23] = v3; + } else { + cv[s + 6] = u1; + cv[s + 7] = v1; + cv[s + 8] = dark.r; + cv[s + 9] = dark.g; + cv[s + 10] = dark.b; + cv[s + 11] = dark.a; + cv[s + 12] = x2; + cv[s + 13] = y2; + cv[s + 14] = light.r; + cv[s + 15] = light.g; + cv[s + 16] = light.b; + cv[s + 17] = light.a; + cv[s + 18] = u2; + cv[s + 19] = v2; + cv[s + 20] = dark.r; + cv[s + 21] = dark.g; + cv[s + 22] = dark.b; + cv[s + 23] = dark.a; + cv[s + 24] = x3; + cv[s + 25] = y3; + cv[s + 26] = light.r; + cv[s + 27] = light.g; + cv[s + 28] = light.b; + cv[s + 29] = light.a; + cv[s + 30] = u3; + cv[s + 31] = v3; + cv[s + 32] = dark.r; + cv[s + 33] = dark.g; + cv[s + 34] = dark.b; + cv[s + 35] = dark.a; + } + s = clippedTriangles.length; + const ct = Utils.setArraySize(clippedTriangles, s + 3); + ct[s] = index; + ct[s + 1] = index + 1; + ct[s + 2] = index + 2; + index += 3; + break; + } + } + } + return clipOutputItems != null; + } + clipTrianglesUnpacked(vertices, vertexStart, triangles, trianglesLength, uvs, stride = 2) { + let clippedVertices = this._clippedVerticesTyped; + let clippedUVs = this._clippedUVsTyped; + let clippedTriangles = this._clippedTrianglesTyped; + let index = 0; + this.clippedVerticesLength = 0; + this.clippedUVsLength = 0; + this.clippedTrianglesLength = 0; + if (this.inverse) { + const polygon = this.clippingPolygons[0]; + for (let i = 0; i < trianglesLength; i += 3) { + let v = triangles[i] * stride; + const x1 = vertices[vertexStart + v], y1 = vertices[vertexStart + v + 1]; + let uv = triangles[i] << 1; + const u1 = uvs[uv], v1 = uvs[uv + 1]; + v = triangles[i + 1] * stride; + const x2 = vertices[vertexStart + v], y2 = vertices[vertexStart + v + 1]; + uv = triangles[i + 1] << 1; + const u2 = uvs[uv], v2 = uvs[uv + 1]; + v = triangles[i + 2] * stride; + const x3 = vertices[vertexStart + v], y3 = vertices[vertexStart + v + 1]; + uv = triangles[i + 2] << 1; + const u3 = uvs[uv], v3 = uvs[uv + 1]; + this.clipInverse(x1, y1, x2, y2, x3, y3, polygon); + const nn = this.inverseVertices.length; + if (nn === 0) continue; + const d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1, d = 1 / (d0 * d2 + d1 * (y1 - y3)); + const iv = this.inverseVertices; + for (let offset = 0; offset < nn; ) { + const polygonSize = iv[offset++]; + const vertexCount = polygonSize >> 1; + let s = this.clippedVerticesLength; + const newLength = s + vertexCount * stride; + const newUVLength = this.clippedUVsLength + vertexCount * 2; + if (clippedVertices.length < newLength) { + this._clippedVerticesTyped = new Float32Array(newLength * 2); + this._clippedVerticesTyped.set(clippedVertices.subarray(0, s)); + clippedVertices = this._clippedVerticesTyped; + } + if (clippedUVs.length < newUVLength) { + this._clippedUVsTyped = new Float32Array(newUVLength * 2); + this._clippedUVsTyped.set(clippedUVs.subarray(0, this.clippedUVsLength)); + clippedUVs = this._clippedUVsTyped; + } + this.clippedVerticesLength = newLength; + this.clippedUVsLength = newUVLength; + const cv = this._clippedVerticesTyped; + const cu = this._clippedUVsTyped; + let uvIndex = newUVLength - vertexCount * 2; + for (let ii = 0; ii < polygonSize; ii += 2, s += stride, uvIndex += 2) { + const x = iv[offset + ii], y = iv[offset + ii + 1]; + cv[s] = x; + cv[s + 1] = y; + const c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cu[uvIndex] = u1 * a + u2 * b + u3 * c; + cu[uvIndex + 1] = v1 * a + v2 * b + v3 * c; + } + s = this.clippedTrianglesLength; + const newLengthTriangles = s + 3 * (vertexCount - 2); + if (clippedTriangles.length < newLengthTriangles) { + this._clippedTrianglesTyped = new Uint16Array(newLengthTriangles * 2); + this._clippedTrianglesTyped.set(clippedTriangles.subarray(0, s)); + clippedTriangles = this._clippedTrianglesTyped; + } + this.clippedTrianglesLength = newLengthTriangles; + const ct = clippedTriangles; + for (let ii = 1; ii < vertexCount - 1; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += vertexCount; + offset += polygonSize; + } + } + this.clippedVerticesTyped = this._clippedVerticesTyped.subarray(0, this.clippedVerticesLength); + this.clippedUVsTyped = this._clippedUVsTyped.subarray(0, this.clippedUVsLength); + this.clippedTrianglesTyped = this._clippedTrianglesTyped.subarray(0, this.clippedTrianglesLength); + return true; + } + const clipOutput = this.clipOutput; + const polygons = this.clippingPolygons; + const polygonsCount = this.clippingPolygons.length; + let clipOutputItems = null; + for (let i = 0; i < trianglesLength; i += 3) { + let t = triangles[i]; + let v = t * stride; + const x1 = vertices[vertexStart + v], y1 = vertices[vertexStart + v + 1]; + let uv = t << 1; + const u1 = uvs[uv], v1 = uvs[uv + 1]; + t = triangles[i + 1]; + v = t * stride; + const x2 = vertices[vertexStart + v], y2 = vertices[vertexStart + v + 1]; + uv = t << 1; + const u2 = uvs[uv], v2 = uvs[uv + 1]; + t = triangles[i + 2]; + v = t * stride; + const x3 = vertices[vertexStart + v], y3 = vertices[vertexStart + v + 1]; + uv = t << 1; + const u3 = uvs[uv], v3 = uvs[uv + 1]; + let d0 = 0, d1 = 0, d2 = 0, d4 = 0, d = 0; + for (let p = 0; p < polygonsCount; p++) { + let s = this.clippedVerticesLength; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p])) { + clipOutputItems = clipOutput; + const clipOutputLength = clipOutput.length; + if (clipOutputLength === 0) continue; + let clipOutputCount = clipOutputLength >> 1; + if (d === 0) { + d0 = y2 - y3; + d1 = x3 - x2; + d2 = x1 - x3; + d4 = y3 - y1; + d = 1 / (d0 * d2 - d1 * d4); + } + const newLength = s + clipOutputCount * stride; + if (clippedVertices.length < newLength) { + this._clippedVerticesTyped = new Float32Array(newLength * 2); + this._clippedVerticesTyped.set(clippedVertices.subarray(0, s)); + this._clippedUVsTyped = new Float32Array((this.clippedUVsLength + clipOutputCount * 2) * 2); + this._clippedUVsTyped.set(clippedUVs.subarray(0, this.clippedUVsLength)); + clippedVertices = this._clippedVerticesTyped; + clippedUVs = this._clippedUVsTyped; + } + const cv = clippedVertices; + const cu = clippedUVs; + this.clippedVerticesLength = newLength; + let uvIndex = this.clippedUVsLength; + this.clippedUVsLength = uvIndex + clipOutputCount * 2; + for (let ii = 0; ii < clipOutputLength; ii += 2, s += stride, uvIndex += 2) { + const x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + cv[s] = x; + cv[s + 1] = y; + const c0 = x - x3, c1 = y - y3, a = (d0 * c0 + d1 * c1) * d, b = (d4 * c0 + d2 * c1) * d, c = 1 - a - b; + cu[uvIndex] = u1 * a + u2 * b + u3 * c; + cu[uvIndex + 1] = v1 * a + v2 * b + v3 * c; + } + s = this.clippedTrianglesLength; + const newLengthTriangles = s + 3 * (clipOutputCount - 2); + if (clippedTriangles.length < newLengthTriangles) { + this._clippedTrianglesTyped = new Uint16Array(newLengthTriangles * 2); + this._clippedTrianglesTyped.set(clippedTriangles.subarray(0, s)); + clippedTriangles = this._clippedTrianglesTyped; + } + this.clippedTrianglesLength = newLengthTriangles; + const ct = clippedTriangles; + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + ct[s] = index; + ct[s + 1] = index + ii; + ct[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let newLength = s + 3 * stride; + if (clippedVertices.length < newLength) { + this._clippedVerticesTyped = new Float32Array(newLength * 2); + this._clippedVerticesTyped.set(clippedVertices.subarray(0, s)); + clippedVertices = this._clippedVerticesTyped; + } + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + stride] = x2; + clippedVertices[s + stride + 1] = y2; + clippedVertices[s + stride * 2] = x3; + clippedVertices[s + stride * 2 + 1] = y3; + const uvLength = this.clippedUVsLength + 3 * 2; + if (clippedUVs.length < uvLength) { + this._clippedUVsTyped = new Float32Array(uvLength * 2); + this._clippedUVsTyped.set(clippedUVs.subarray(0, this.clippedUVsLength)); + clippedUVs = this._clippedUVsTyped; + } + const uvIndex = this.clippedUVsLength; + clippedUVs[uvIndex] = u1; + clippedUVs[uvIndex + 1] = v1; + clippedUVs[uvIndex + 2] = u2; + clippedUVs[uvIndex + 3] = v2; + clippedUVs[uvIndex + 4] = u3; + clippedUVs[uvIndex + 5] = v3; + this.clippedVerticesLength = newLength; + this.clippedUVsLength = uvLength; + s = this.clippedTrianglesLength; + newLength = s + 3; + if (clippedTriangles.length < newLength) { + this._clippedTrianglesTyped = new Uint16Array(newLength * 2); + this._clippedTrianglesTyped.set(clippedTriangles.subarray(0, s)); + clippedTriangles = this._clippedTrianglesTyped; + } + const ct = clippedTriangles; + ct[s] = index; + ct[s + 1] = index + 1; + ct[s + 2] = index + 2; + index += 3; + this.clippedTrianglesLength = newLength; + break; + } + } + } + this.clippedVerticesTyped = this._clippedVerticesTyped.subarray(0, this.clippedVerticesLength); + this.clippedUVsTyped = this._clippedUVsTyped.subarray(0, this.clippedUVsLength); + this.clippedTrianglesTyped = this._clippedTrianglesTyped.subarray(0, this.clippedTrianglesLength); + return clipOutputItems !== null; + } + clip(x1, y1, x2, y2, x3, y3, polygon) { + const originalOutput = this.clipOutput; + let clipped = false; + let input, output; + if (polygon.length % 4 >= 2) { + input = this.clipOutput; + output = this.scratch; + } else { + input = this.scratch; + output = this.clipOutput; + } + const v = polygon; + input.length = 8; + const iv = input; + iv[0] = x1; + iv[1] = y1; + iv[2] = x2; + iv[3] = y2; + iv[4] = x3; + iv[5] = y3; + iv[6] = x1; + iv[7] = y1; + output.length = 0; + const last = polygon.length - 4; + for (let i = 0; ; i += 2) { + const edgeX = v[i], edgeY = v[i + 1], ex = edgeX - v[i + 2], ey = edgeY - v[i + 3]; + const outputStart = output.length; + const iv2 = input; + x1 = iv2[0]; + y1 = iv2[1]; + let s1 = ey * (edgeX - x1) - ex * (edgeY - y1); + for (let ii = 2, nn = input.length - 2; ii <= nn; ii += 2) { + x2 = iv2[ii]; + y2 = iv2[ii + 1]; + const s2 = ey * (edgeX - x2) - ex * (edgeY - y2); + if (s1 > 0) { + if (s2 > 0) + output.push(x2, y2); + else { + const ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(x1 + ix * t, y1 + iy * t); + clipped = true; + } else + output.push(x2, y2); + } + } else if (s2 > 0) { + const ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(x1 + ix * t, y1 + iy * t, x2, y2); + clipped = true; + } else + output.push(x2, y2); + } else + clipped = true; + x1 = x2; + y1 = y2; + s1 = s2; + } + if (outputStart === output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0], output[1]); + if (i === last) break; + const temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput !== output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + clipInverse(x1, y1, x2, y2, x3, y3, polygon) { + this.inverseVertices.length = 0; + const vLast = polygon.length - 4; + let input, output; + if (polygon.length % 4 >= 2) { + input = this.clipOutput; + output = this.scratch; + } else { + input = this.scratch; + output = this.clipOutput; + } + input.length = 8; + let v = polygon, iv = input; + iv[0] = x1; + iv[1] = y1; + iv[2] = x2; + iv[3] = y2; + iv[4] = x3; + iv[5] = y3; + iv[6] = x1; + iv[7] = y1; + output.length = 0; + for (let i = 0; ; i += 2) { + const edgeX = v[i], edgeY = v[i + 1], ex = edgeX - v[i + 2], ey = edgeY - v[i + 3]; + const outputStart = output.length, fragmentStart = this.inverseVertices.length; + this.inverseVertices.push(0); + iv = input; + x1 = iv[0]; + y1 = iv[1]; + let s1 = ey * (edgeX - x1) - ex * (edgeY - y1); + for (let ii = 2, nn = input.length - 2; ii <= nn; ii += 2) { + x2 = iv[ii]; + y2 = iv[ii + 1]; + const s2 = ey * (edgeX - x2) - ex * (edgeY - y2); + if (s1 > 0) { + if (s2 > 0) + output.push(x2, y2); + else { + const ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + const cx = x1 + ix * t, cy = y1 + iy * t; + output.push(cx, cy); + this.inverseVertices.push(cx, cy, x2, y2); + } else + output.push(x2, y2); + } + } else if (s2 > 0) { + const ix = x2 - x1, iy = y2 - y1, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + const cx = x1 + ix * t, cy = y1 + iy * t; + this.inverseVertices.push(cx, cy); + output.push(cx, cy, x2, y2); + } else + output.push(x2, y2); + } else + this.inverseVertices.push(x2, y2); + x1 = x2; + y1 = y2; + s1 = s2; + } + const fragmentSize = this.inverseVertices.length - fragmentStart - 1; + if (fragmentSize >= 6) + this.inverseVertices[fragmentStart] = fragmentSize; + else + this.inverseVertices.length = fragmentStart; + if (outputStart === output.length) break; + output.push(output[0], output[1]); + if (i === vLast) break; + const temp = output; + output = input; + output.length = 0; + input = temp; + } + } + makeClockwise(polygon) { + const v = polygon; + const n = polygon.length; + let noCW = true, noCCW = true; + let area = 0, prevX = v[n - 2], prevY = v[n - 1], currX = v[0], currY = v[1]; + for (let i = 2; i < n; i += 2) { + const nextX = v[i], nextY = v[i + 1]; + area += currX * nextY - nextX * currY; + const cross2 = (currX - prevX) * (nextY - currY) - (currY - prevY) * (nextX - currX); + noCCW = noCCW && cross2 <= 0; + noCW = noCW && cross2 >= 0; + prevX = currX; + prevY = currY; + currX = nextX; + currY = nextY; + } + area += currX * v[1] - v[0] * currY; + const cross = (currX - prevX) * (v[1] - currY) - (currY - prevY) * (v[0] - currX); + noCCW = noCCW && cross <= 0; + noCW = noCW && cross >= 0; + if (area >= 0) { + for (let i = 0, lastX = n - 2, half = n >> 1; i < half; i += 2) { + const x = v[i], y = v[i + 1]; + const other = lastX - i; + v[i] = v[other]; + v[i + 1] = v[other + 1]; + v[other] = x; + v[other + 1] = y; + } + return noCW; + } + return noCCW; + } + makeConvex(polygon) { + const n = polygon.length; + const v = polygon; + this.clipOutput.length = n; + const sorted = this.clipOutput; + sorted[0] = v[0]; + sorted[1] = v[1]; + for (let i = 2; i < n; i += 2) { + const x = v[i], y = v[i + 1]; + let p = i - 2; + for (; p >= 0 && (sorted[p] > x || sorted[p] === x && sorted[p + 1] > y); p -= 2) { + sorted[p + 2] = sorted[p]; + sorted[p + 3] = sorted[p + 1]; + } + sorted[p + 2] = x; + sorted[p + 3] = y; + } + v[0] = sorted[0]; + v[1] = sorted[1]; + v[2] = sorted[2]; + v[3] = sorted[3]; + let s = 4; + for (let i = 4; i < n; i += 2, s += 2) { + const x = sorted[i], y = sorted[i + 1]; + while ((v[s - 2] - v[s - 4]) * (y - v[s - 3]) - (v[s - 1] - v[s - 3]) * (x - v[s - 4]) >= 0) { + s -= 2; + if (s === 2) break; + } + v[s] = x; + v[s + 1] = y; + } + v[s] = sorted[n - 4]; + v[s + 1] = sorted[n - 3]; + const t = s; + s += 2; + for (let i = n - 6; i >= 0; i -= 2, s += 2) { + const x = sorted[i], y = sorted[i + 1]; + while ((v[s - 2] - v[s - 4]) * (y - v[s - 3]) - (v[s - 1] - v[s - 3]) * (x - v[s - 4]) >= 0) { + s -= 2; + if (s === t) break; + } + v[s] = x; + v[s + 1] = y; + } + polygon.length = s - 2; + } + }; + + // spine-core/src/SkeletonJson.ts + var SkeletonJson = class { + attachmentLoader; + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + linkedMeshes = []; + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema + readSkeletonData(json) { + const scale = this.scale; + const skeletonData = new SkeletonData(); + const root = typeof json === "string" ? JSON.parse(json) : json; + const skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.referenceScale = getValue(skeletonMap, "referenceScale", 100) * scale; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images ?? null; + skeletonData.audioPath = skeletonMap.audio ?? null; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + const boneMap = root.bones[i]; + let parent = null; + const parentName = getValue(boneMap, "parent", null); + if (parentName) parent = skeletonData.findBone(parentName); + const data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + const setup = data.setupPose; + setup.x = getValue(boneMap, "x", 0) * scale; + setup.y = getValue(boneMap, "y", 0) * scale; + setup.rotation = getValue(boneMap, "rotation", 0); + setup.scaleX = getValue(boneMap, "scaleX", 1); + setup.scaleY = getValue(boneMap, "scaleY", 1); + setup.shearX = getValue(boneMap, "shearX", 0); + setup.shearY = getValue(boneMap, "shearY", 0); + setup.inherit = Utils.enumValue(Inherit, getValue(boneMap, "inherit", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + const color = getValue(boneMap, "color", null); + if (color) data.color.setFromString(color); + data.icon = getValue(boneMap, "icon", void 0); + data.iconSize = getValue(boneMap, "iconSize", 1); + data.iconRotation = getValue(boneMap, "iconRotation", 0); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + const slotMap = root.slots[i]; + const slotName = slotMap.name; + const boneData = skeletonData.findBone(slotMap.bone); + if (!boneData) throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`); + const data = new SlotData(skeletonData.slots.length, slotName, boneData); + const color = getValue(slotMap, "color", null); + if (color) data.setupPose.color.setFromString(color); + const dark = getValue(slotMap, "dark", null); + if (dark) data.setupPose.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + data.visible = getValue(slotMap, "visible", true); + skeletonData.slots.push(data); + } + } + if (root.constraints) { + for (const constraintMap of root.constraints) { + const name = constraintMap.name; + const skinRequired = getValue(constraintMap, "skin", false); + switch (getValue(constraintMap, "type", false)) { + case "ik": { + const data = new IkConstraintData(name); + data.skinRequired = skinRequired; + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + const bone = skeletonData.findBone(constraintMap.bones[ii]); + if (!bone) throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${name}.`); + data.bones.push(bone); + } + const targetName = constraintMap.target; + const target = skeletonData.findBone(targetName); + if (!target) throw new Error(`Couldn't find target bone ${targetName} for IK constraint ${name}.`); + data.target = target; + const scaleY = getValue(constraintMap, "scaleY", null); + if (scaleY != null) data.scaleYMode = Utils.enumValue(ScaleYMode, scaleY); + const setup = data.setupPose; + setup.mix = getValue(constraintMap, "mix", 1); + setup.softness = getValue(constraintMap, "softness", 0) * scale; + setup.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + setup.compress = getValue(constraintMap, "compress", false); + setup.stretch = getValue(constraintMap, "stretch", false); + skeletonData.constraints.push(data); + break; + } + case "transform": { + const data = new TransformConstraintData(name); + data.skinRequired = skinRequired; + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + const boneName = constraintMap.bones[ii]; + const bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + const sourceName = constraintMap.source; + const source = skeletonData.findBone(sourceName); + if (!source) throw new Error(`Couldn't find source bone ${sourceName} for transform constraint ${constraintMap.name}.`); + data.source = source; + data.localSource = getValue(constraintMap, "localSource", false); + data.localTarget = getValue(constraintMap, "localTarget", false); + data.additive = getValue(constraintMap, "additive", false); + data.clamp = getValue(constraintMap, "clamp", false); + let rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false; + const fromEntries = Object.entries(getValue(constraintMap, "properties", {})); + for (const [name2, fromEntry] of fromEntries) { + const from = this.fromProperty(name2); + const fromScale = this.propertyScale(name2, scale); + from.offset = getValue(fromEntry, "offset", 0) * fromScale; + const toEntries = Object.entries(getValue(fromEntry, "to", {})); + for (const [name3, toEntry] of toEntries) { + let toScale = 1; + let to; + switch (name3) { + case "rotate": { + rotate = true; + to = new ToRotate(); + break; + } + case "x": { + x = true; + to = new ToX(); + toScale = scale; + break; + } + case "y": { + y = true; + to = new ToY(); + toScale = scale; + break; + } + case "scaleX": { + scaleX = true; + to = new ToScaleX(); + break; + } + case "scaleY": { + scaleY = true; + to = new ToScaleY(); + break; + } + case "shearY": { + shearY = true; + to = new ToShearY(); + break; + } + default: + throw new Error(`Invalid transform constraint to property: ${name3}`); + } + to.offset = getValue(toEntry, "offset", 0) * toScale; + to.max = getValue(toEntry, "max", 1) * toScale; + to.scale = getValue(toEntry, "scale", 1) * toScale / fromScale; + from.to.push(to); + } + if (from.to.length > 0) data.properties.push(from); + } + data.offsets[TransformConstraintData.ROTATION] = getValue(constraintMap, "rotation", 0); + data.offsets[TransformConstraintData.X] = getValue(constraintMap, "x", 0) * scale; + data.offsets[TransformConstraintData.Y] = getValue(constraintMap, "y", 0) * scale; + data.offsets[TransformConstraintData.SCALEX] = getValue(constraintMap, "scaleX", 0); + data.offsets[TransformConstraintData.SCALEY] = getValue(constraintMap, "scaleY", 0); + data.offsets[TransformConstraintData.SHEARY] = getValue(constraintMap, "shearY", 0); + const setup = data.setupPose; + if (rotate) setup.mixRotate = getValue(constraintMap, "mixRotate", 1); + if (x) setup.mixX = getValue(constraintMap, "mixX", 1); + if (y) setup.mixY = getValue(constraintMap, "mixY", setup.mixX); + if (scaleX) setup.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + if (scaleY) setup.mixScaleY = getValue(constraintMap, "mixScaleY", setup.mixScaleX); + if (shearY) setup.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.constraints.push(data); + break; + } + case "path": { + const data = new PathConstraintData(name); + data.skinRequired = skinRequired; + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + const boneName = constraintMap.bones[ii]; + const bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + const slotName = constraintMap.slot; + const slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error(`Couldn't find slot ${slotName} for path constraint ${constraintMap.name}.`); + data.slot = slot; + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + const setup = data.setupPose; + setup.position = getValue(constraintMap, "position", 0); + if (data.positionMode === 0 /* Fixed */) setup.position *= scale; + setup.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode === 0 /* Length */ || data.spacingMode === 1 /* Fixed */) setup.spacing *= scale; + setup.mixRotate = getValue(constraintMap, "mixRotate", 1); + setup.mixX = getValue(constraintMap, "mixX", 1); + setup.mixY = getValue(constraintMap, "mixY", setup.mixX); + skeletonData.constraints.push(data); + break; + } + case "physics": { + const data = new PhysicsConstraintData(name); + data.skinRequired = skinRequired; + const boneName = constraintMap.bone; + const bone = skeletonData.findBone(boneName); + if (bone == null) throw new Error(`Physics bone not found: ${boneName}`); + data.bone = bone; + data.x = getValue(constraintMap, "x", 0); + data.y = getValue(constraintMap, "y", 0); + data.rotate = getValue(constraintMap, "rotate", 0); + data.scaleX = getValue(constraintMap, "scaleX", 0); + const scaleY = getValue(constraintMap, "scaleY", null); + if (scaleY != null) data.scaleYMode = Utils.enumValue(ScaleYMode, scaleY); + data.shearX = getValue(constraintMap, "shearX", 0); + data.limit = getValue(constraintMap, "limit", 5e3) * scale; + data.step = 1 / getValue(constraintMap, "fps", 60); + const setup = data.setupPose; + setup.inertia = getValue(constraintMap, "inertia", 0.5); + setup.strength = getValue(constraintMap, "strength", 100); + setup.damping = getValue(constraintMap, "damping", 0.85); + setup.massInverse = 1 / getValue(constraintMap, "mass", 1); + setup.wind = getValue(constraintMap, "wind", 0); + setup.gravity = getValue(constraintMap, "gravity", 0); + setup.mix = getValue(constraintMap, "mix", 1); + data.inertiaGlobal = getValue(constraintMap, "inertiaGlobal", false); + data.strengthGlobal = getValue(constraintMap, "strengthGlobal", false); + data.dampingGlobal = getValue(constraintMap, "dampingGlobal", false); + data.massGlobal = getValue(constraintMap, "massGlobal", false); + data.windGlobal = getValue(constraintMap, "windGlobal", false); + data.gravityGlobal = getValue(constraintMap, "gravityGlobal", false); + data.mixGlobal = getValue(constraintMap, "mixGlobal", false); + skeletonData.constraints.push(data); + break; + } + case "slider": { + const data = new SliderData(name); + data.skinRequired = skinRequired; + data.additive = getValue(constraintMap, "additive", false); + data.loop = getValue(constraintMap, "loop", false); + data.setupPose.mix = getValue(constraintMap, "mix", 1); + const boneName = constraintMap.bone; + if (boneName) { + data.bone = skeletonData.findBone(boneName); + if (!data.bone) throw new Error(`Slider bone not found: ${boneName}`); + const property = constraintMap.property; + data.property = this.fromProperty(property); + const propertyScale = this.propertyScale(property, scale); + data.property.offset = getValue(constraintMap, "from", 0) * propertyScale; + data.offset = getValue(constraintMap, "to", 0); + data.scale = getValue(constraintMap, "scale", 1) / propertyScale; + data.max = getValue(constraintMap, "max", 0); + data.local = getValue(constraintMap, "local", false); + } else + data.setupPose.time = getValue(constraintMap, "time", 0); + skeletonData.constraints.push(data); + break; + } + } + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + const skinMap = root.skins[i]; + const skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) { + const boneName = skinMap.bones[ii]; + const bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) { + const constraintName = skinMap.ik[ii]; + const constraint = skeletonData.findConstraint(constraintName, IkConstraintData); + if (!constraint) throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) { + const constraintName = skinMap.transform[ii]; + const constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); + if (!constraint) throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) { + const constraintName = skinMap.path[ii]; + const constraint = skeletonData.findConstraint(constraintName, PathConstraintData); + if (!constraint) throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.physics) { + for (let ii = 0; ii < skinMap.physics.length; ii++) { + const constraintName = skinMap.physics[ii]; + const constraint = skeletonData.findConstraint(constraintName, PhysicsConstraintData); + if (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.slider) { + for (let ii = 0; ii < skinMap.slider.length; ii++) { + const constraintName = skinMap.slider[ii]; + const constraint = skeletonData.findConstraint(constraintName, SliderData); + if (!constraint) throw new Error(`Couldn't find slider constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (const slotName in skinMap.attachments) { + const slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error(`Couldn't find skin slot ${slotName} for skin ${skinMap.name}.`); + const slotMap = skinMap.attachments[slotName]; + for (const entryName in slotMap) { + const attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name === "default") skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + const linkedMesh = this.linkedMeshes[i]; + const skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) throw new Error(`Skin not found: ${linkedMesh.skin}`); + const source = skin.getAttachment(linkedMesh.sourceIndex, linkedMesh.source); + if (!source) throw new Error(`Source mesh not found: ${linkedMesh.source}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimelines ? source : linkedMesh.mesh; + linkedMesh.mesh.setSourceMesh(source); + linkedMesh.mesh.updateSequence(); + outer: + if (linkedMesh.inheritTimelines && linkedMesh.slotIndex !== linkedMesh.sourceIndex) { + const slots = source.timelineSlots; + for (const existing of slots) + if (existing === linkedMesh.slotIndex) break outer; + const newSlots = [...slots]; + newSlots[slots.length] = linkedMesh.slotIndex; + source.timelineSlots = newSlots; + } + } + this.linkedMeshes.length = 0; + if (root.events) { + for (const eventName in root.events) { + const eventMap = root.events[eventName]; + const data = new EventData(eventName); + const setup = data.setupPose; + setup.intValue = getValue(eventMap, "int", 0); + setup.floatValue = getValue(eventMap, "float", 0); + setup.stringValue = getValue(eventMap, "string", ""); + data._audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + setup.volume = getValue(eventMap, "volume", setup.volume); + setup.balance = getValue(eventMap, "balance", setup.balance); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (const animationName in root.animations) { + const animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + if (root.constraints) { + for (const animationName in root.constraints) { + const animationMap = root.constraints[animationName]; + if (animationMap.type === "slider") { + const data = skeletonData.findConstraint(animationMap.name, SliderData); + const animationName2 = animationMap.animation; + const animation = skeletonData.findAnimation(animationName2); + if (!animation) throw new Error(`Slider animation not found: ${animationName2}`); + data.animation = animation; + } + } + } + return skeletonData; + } + fromProperty(type) { + let from; + switch (type) { + case "rotate": + from = new FromRotate(); + break; + case "x": + from = new FromX(); + break; + case "y": + from = new FromY(); + break; + case "scaleX": + from = new FromScaleX(); + break; + case "scaleY": + from = new FromScaleY(); + break; + case "shearY": + from = new FromShearY(); + break; + default: + throw new Error(`Invalid transform constraint from property: ${type}`); + } + return from; + } + propertyScale(type, scale) { + switch (type) { + case "x": + case "y": + return scale; + default: + return 1; + } + } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema + readAttachment(map, skin, slotIndex, placeholder, skeletonData) { + const scale = this.scale; + const name = getValue(map, "name", placeholder); + switch (getValue(map, "type", "region")) { + case "region": { + const path = getValue(map, "path", name); + const sequence = this.readSequence(getValue(map, "sequence", null)); + const region = this.attachmentLoader.newRegionAttachment(skin, placeholder, name, path, sequence); + if (!region) return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + const color = getValue(map, "color", null); + if (color) region.color.setFromString(color); + region.updateSequence(); + return region; + } + case "boundingbox": { + const box = this.attachmentLoader.newBoundingBoxAttachment(skin, placeholder, name); + if (!box) return null; + this.readVertices(map, box, map.vertexCount << 1); + const color = getValue(map, "color", null); + if (color) box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + const path = getValue(map, "path", name); + const sequence = this.readSequence(getValue(map, "sequence", null)); + const mesh = this.attachmentLoader.newMeshAttachment(skin, placeholder, name, path, sequence); + if (!mesh) return null; + mesh.path = path; + const color = getValue(map, "color", null); + if (color) mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + const source = getValue(map, "source", null); + if (source) { + let sourceIndex = slotIndex; + const slot = getValue(map, "slot", null); + if (slot) { + const sourceSlot = skeletonData.findSlot(slot); + if (!sourceSlot) throw new Error(`Source mesh slot not found: ${slot}`); + sourceIndex = sourceSlot.index; + } + this.linkedMeshes.push(new LinkedMesh2( + mesh, + getValue(map, "skin", null), + slotIndex, + sourceIndex, + source, + getValue(map, "timelines", true) + )); + return mesh; + } + const uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + mesh.updateSequence(); + return mesh; + } + case "path": { + const path = this.attachmentLoader.newPathAttachment(skin, placeholder, name); + if (!path) return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + const vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + const lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + const color = getValue(map, "color", null); + if (color) path.color.setFromString(color); + return path; + } + case "point": { + const point = this.attachmentLoader.newPointAttachment(skin, placeholder, name); + if (!point) return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + const color = getValue(map, "color", null); + if (color) point.color.setFromString(color); + return point; + } + case "clipping": { + const clip = this.attachmentLoader.newClippingAttachment(skin, placeholder, name); + if (!clip) return null; + const end = getValue(map, "end", null); + if (end) clip.endSlot = skeletonData.findSlot(end); + clip.convex = getValue(map, "convex", false); + clip.inverse = getValue(map, "inverse", false); + const vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + const color = getValue(map, "color", null); + if (color) clip.color.setFromString(color); + return clip; + } + } + return null; + } + readSequence(map) { + if (map == null) return new Sequence(1, false); + const sequence = new Sequence(getValue(map, "count", 0), true); + sequence.start = getValue(map, "start", 1); + sequence.digits = getValue(map, "digits", 0); + sequence.setupIndex = getValue(map, "setup", 0); + return sequence; + } + // biome-ignore lint/suspicious/noExplicitAny: it is any until we define a schema + readVertices(map, attachment, verticesLength) { + const scale = this.scale; + attachment.worldVerticesLength = verticesLength; + const vertices = map.vertices; + if (verticesLength === vertices.length) { + const scaledVertices = Utils.toFloatArray(vertices); + if (scale !== 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + const weights = []; + const bones = []; + for (let i = 0, n = vertices.length; i < n; ) { + const boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + // biome-ignore lint/suspicious/noExplicitAny: it is any untile we define a schema + readAnimation(map, name, skeletonData) { + const scale = this.scale; + const timelines = []; + if (map.slots) { + for (const slotName in map.slots) { + const slotMap = map.slots[slotName]; + const slot = skeletonData.findSlot(slotName); + if (!slot) throw new Error(`Slot not found: ${slotName}`); + const slotIndex = slot.index; + for (const timelineName in slotMap) { + const timelineMap = slotMap[timelineName]; + if (!timelineMap) continue; + const frames = timelineMap.length; + switch (timelineName) { + case "attachment": { + const timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + const keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); + } + timelines.push(timeline); + break; + } + case "rgba": { + const timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color2 = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color2.r, color2.g, color2.b, color2.a); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.color); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color2.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color2.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color2.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.a, newColor.a, 1); + } + time = time2; + color2 = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + break; + } + case "rgb": { + const timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color2 = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color2.r, color2.g, color2.b); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.color); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color2.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color2.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color2.b, newColor.b, 1); + } + time = time2; + color2 = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + break; + } + case "alpha": { + readTimeline12(timelines, timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1); + break; + } + case "rgba2": { + const timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color2 = Color.fromString(keyMap.light); + let color22 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color2.r, color2.g, color2.b, color2.a, color22.r, color22.g, color22.b); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.light); + const newColor2 = Color.fromString(nextMap.dark); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color2.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color2.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color2.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color22.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color22.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color22.b, newColor2.b, 1); + } + time = time2; + color2 = newColor; + color22 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + break; + } + case "rgb2": { + const timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color2 = Color.fromString(keyMap.light); + let color22 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color2.r, color2.g, color2.b, color22.r, color22.g, color22.b); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const newColor = Color.fromString(nextMap.light); + const newColor2 = Color.fromString(nextMap.dark); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color2.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color2.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color2.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color22.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color22.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color22.b, newColor2.b, 1); + } + time = time2; + color2 = newColor; + color22 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + break; + } + default: + throw new Error(`Invalid timeline type for a slot: ${timelineMap.name} (${slotMap.name})`); + } + } + } + } + if (map.bones) { + for (const boneName in map.bones) { + const boneMap = map.bones[boneName]; + const bone = skeletonData.findBone(boneName); + if (!bone) throw new Error(`Bone not found: ${boneName}`); + const boneIndex = bone.index; + for (const timelineName in boneMap) { + const timelineMap = boneMap[timelineName]; + const frames = timelineMap.length; + if (frames === 0) continue; + switch (timelineName) { + case "rotate": + readTimeline12(timelines, timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1); + break; + case "translate": + readTimeline22(timelines, timelineMap, new TranslateTimeline(frames, frames << 1, boneIndex), "x", "y", 0, scale); + break; + case "translatex": + readTimeline12(timelines, timelineMap, new TranslateXTimeline(frames, frames, boneIndex), 0, scale); + break; + case "translatey": + readTimeline12(timelines, timelineMap, new TranslateYTimeline(frames, frames, boneIndex), 0, scale); + break; + case "scale": + readTimeline22(timelines, timelineMap, new ScaleTimeline(frames, frames << 1, boneIndex), "x", "y", 1, 1); + break; + case "scalex": + readTimeline12(timelines, timelineMap, new ScaleXTimeline(frames, frames, boneIndex), 1, 1); + break; + case "scaley": + readTimeline12(timelines, timelineMap, new ScaleYTimeline(frames, frames, boneIndex), 1, 1); + break; + case "shear": + readTimeline22(timelines, timelineMap, new ShearTimeline(frames, frames << 1, boneIndex), "x", "y", 0, 1); + break; + case "shearx": + readTimeline12(timelines, timelineMap, new ShearXTimeline(frames, frames, boneIndex), 0, 1); + break; + case "sheary": + readTimeline12(timelines, timelineMap, new ShearYTimeline(frames, frames, boneIndex), 0, 1); + break; + case "inherit": { + const timeline = new InheritTimeline(frames, bone.index); + for (let frame = 0; frame < timelineMap.length; frame++) { + const aFrame = timelineMap[frame]; + timeline.setFrame(frame, getValue(aFrame, "time", 0), Utils.enumValue(Inherit, getValue(aFrame, "inherit", "Normal"))); + } + timelines.push(timeline); + break; + } + default: + throw new Error(`Invalid timeline type for a bone: ${timelineMap.name} (${boneMap.name})`); + } + } + } + } + if (map.ik) { + for (const constraintName in map.ik) { + const constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) continue; + const constraint = skeletonData.findConstraint(constraintName, IkConstraintData); + if (!constraint) throw new Error(`IK Constraint not found: ${constraintName}`); + const timeline = new IkConstraintTimeline( + constraintMap.length, + constraintMap.length << 1, + skeletonData.constraints.indexOf(constraint) + ); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + const nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const mix2 = getValue(nextMap, "mix", 1); + const softness2 = getValue(nextMap, "softness", 0) * scale; + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (const constraintName in map.transform) { + const timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + const constraint = skeletonData.findConstraint(constraintName, TransformConstraintData); + if (!constraint) throw new Error(`Transform constraint not found: ${constraintName}`); + const timeline = new TransformConstraintTimeline( + timelineMap.length, + timelineMap.length * 6, + skeletonData.constraints.indexOf(constraint) + ); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1), mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1), mixScaleY = getValue(keyMap, "mixScaleY", 1); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const mixRotate2 = getValue(nextMap, "mixRotate", 1); + const mixX2 = getValue(nextMap, "mixX", 1), mixY2 = getValue(nextMap, "mixY", mixX2); + const mixScaleX2 = getValue(nextMap, "mixScaleX", 1), mixScaleY2 = getValue(nextMap, "mixScaleY", 1); + const mixShearY2 = getValue(nextMap, "mixShearY", 1); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (const constraintName in map.path) { + const constraintMap = map.path[constraintName]; + const constraint = skeletonData.findConstraint(constraintName, PathConstraintData); + if (!constraint) throw new Error(`Path constraint not found: ${constraintName}`); + const index = skeletonData.constraints.indexOf(constraint); + for (const timelineName in constraintMap) { + const timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + const frames = timelineMap.length; + switch (timelineName) { + case "position": { + const timeline = new PathConstraintPositionTimeline(frames, frames, index); + readTimeline12(timelines, timelineMap, timeline, 0, constraint.positionMode === 0 /* Fixed */ ? scale : 1); + break; + } + case "spacing": { + const timeline = new PathConstraintSpacingTimeline(frames, frames, index); + readTimeline12(timelines, timelineMap, timeline, 0, constraint.spacingMode === 0 /* Length */ || constraint.spacingMode === 1 /* Fixed */ ? scale : 1); + break; + } + case "mix": { + const timeline = new PathConstraintMixTimeline(frames, frames * 3, index); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const mixRotate2 = getValue(nextMap, "mixRotate", 1); + const mixX2 = getValue(nextMap, "mixX", 1); + const mixY2 = getValue(nextMap, "mixY", mixX2); + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + break; + } + } + } + } + } + if (map.physics) { + for (const constraintName in map.physics) { + const constraintMap = map.physics[constraintName]; + let index = -1; + if (constraintName.length > 0) { + const constraint = skeletonData.findConstraint(constraintName, PhysicsConstraintData); + if (!constraint) throw new Error(`Physics constraint not found: ${constraintName}`); + index = skeletonData.constraints.indexOf(constraint); + } + for (const timelineName in constraintMap) { + const timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + const frames = timelineMap.length; + let timeline; + let defaultValue = 0; + if (timelineName === "reset") { + const resetTimeline = new PhysicsConstraintResetTimeline(frames, index); + for (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++) + resetTimeline.setFrame(frame, getValue(keyMap, "time", 0)); + timelines.push(resetTimeline); + continue; + } + switch (timelineName) { + case "inertia": + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, index); + break; + case "strength": + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, index); + break; + case "damping": + timeline = new PhysicsConstraintDampingTimeline(frames, frames, index); + break; + case "mass": + timeline = new PhysicsConstraintMassTimeline(frames, frames, index); + break; + case "wind": + timeline = new PhysicsConstraintWindTimeline(frames, frames, index); + break; + case "gravity": + timeline = new PhysicsConstraintGravityTimeline(frames, frames, index); + break; + case "mix": { + defaultValue = 1; + timeline = new PhysicsConstraintMixTimeline(frames, frames, index); + break; + } + default: + continue; + } + readTimeline12(timelines, timelineMap, timeline, defaultValue, 1); + } + } + } + if (map.slider) { + for (const constraintName in map.slider) { + const constraintMap = map.slider[constraintName]; + const constraint = skeletonData.findConstraint(constraintName, SliderData); + if (!constraint) throw new Error(`Slider not found: ${constraintName}`); + const index = skeletonData.constraints.indexOf(constraint); + for (const timelineName in constraintMap) { + const timelineMap = constraintMap[timelineName]; + const keyMap = timelineMap[0]; + if (!keyMap) continue; + const frames = timelineMap.length; + switch (timelineName) { + case "time": + readTimeline12(timelines, timelineMap, new SliderTimeline(frames, frames, index), 1, 1); + break; + case "mix": + readTimeline12(timelines, timelineMap, new SliderMixTimeline(frames, frames, index), 1, 1); + break; + } + } + } + } + if (map.attachments) { + for (const attachmentsName in map.attachments) { + const attachmentsMap = map.attachments[attachmentsName]; + const skin = skeletonData.findSkin(attachmentsName); + if (!skin) throw new Error(`Skin not found: ${attachmentsName}`); + for (const slotMapName in attachmentsMap) { + const slotMap = attachmentsMap[slotMapName]; + const slot = skeletonData.findSlot(slotMapName); + if (!slot) throw new Error(`Attachment slot not found: ${slotMapName}`); + const slotIndex = slot.index; + for (const attachmentMapName in slotMap) { + const attachmentMap = slotMap[attachmentMapName]; + const attachment = skin.getAttachment(slotIndex, attachmentMapName); + if (!attachment) throw new Error(`Timeline attachment not found: ${attachmentMapName}`); + for (const timelineMapName in attachmentMap) { + const timelineMap = attachmentMap[timelineMapName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + if (timelineMapName === "deform") { + const weighted = attachment.bones; + const vertices = attachment.vertices; + const deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + const timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + const verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + const start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale !== 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + const nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + const time2 = getValue(nextMap, "time", 0); + const curve = keyMap.curve; + if (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineMapName === "sequence") { + const timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment); + let lastDelay = 0; + for (let frame = 0; frame < timelineMap.length; frame++) { + const delay = getValue(keyMap, "delay", lastDelay); + const time = getValue(keyMap, "time", 0); + const mode = SequenceMode[getValue(keyMap, "mode", "hold")]; + const index = getValue(keyMap, "index", 0); + timeline.setFrame(frame, time, mode, index, delay); + lastDelay = delay; + keyMap = timelineMap[frame + 1]; + } + timelines.push(timeline); + } + } + } + } + } + } + if (map.drawOrder) { + const timeline = new DrawOrderTimeline(map.drawOrder.length); + const slotCount = skeletonData.slots.length; + let frame = 0; + for (const drawOrderMap of map.drawOrder) { + timeline.setFrame(frame++, getValue(drawOrderMap, "time", 0), readDrawOrder2(skeletonData, drawOrderMap, slotCount, null)); + } + timelines.push(timeline); + } + if (map.drawOrderFolder) { + for (const timelineMap of map.drawOrderFolder) { + const slotEntries = getValue(timelineMap, "slots", []); + const folderSlots = new Array(slotEntries.length); + let ii = 0; + for (const slotEntry of slotEntries) { + const slot = skeletonData.findSlot(slotEntry); + if (!slot) throw new Error(`Draw order folder slot not found: ${slotEntry}`); + folderSlots[ii++] = slot.index; + } + const drawOrderFolderEntries = getValue(timelineMap, "keys", []); + const timeline = new DrawOrderFolderTimeline(drawOrderFolderEntries.length, folderSlots, skeletonData.slots.length); + let frame = 0; + for (const drawOrderFolderMap of drawOrderFolderEntries) { + timeline.setFrame(frame++, getValue(drawOrderFolderMap, "time", 0), readDrawOrder2(skeletonData, drawOrderFolderMap, folderSlots.length, folderSlots)); + } + timelines.push(timeline); + } + } + if (map.events) { + const timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + const eventMap = map.events[i]; + const data = skeletonData.findEvent(eventMap.name); + if (!data) throw new Error(`Event not found: ${eventMap.name}`); + const setup = data.setupPose; + const event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), data); + event.intValue = getValue(eventMap, "int", setup.intValue); + event.floatValue = getValue(eventMap, "float", setup.floatValue); + event.stringValue = getValue(eventMap, "string", setup.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", setup.volume); + event.balance = getValue(eventMap, "balance", setup.volume); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + const animation = new Animation(name, timelines, duration); + const color = getValue(map, "color", null); + if (color !== null) animation.color.setFromString(color); + skeletonData.animations.push(animation); + } + }; + var LinkedMesh2 = class { + source; + skin; + slotIndex; + sourceIndex; + mesh; + inheritTimelines; + constructor(mesh, skin, slotIndex, sourceIndex, source, inheritTimelines) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.sourceIndex = sourceIndex; + this.source = source; + this.inheritTimelines = inheritTimelines; + } + }; + function readTimeline12(timelines, keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = keyMap.time ?? 0; + let value = (keyMap.value ?? defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + const nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + timelines.push(timeline); + return; + } + const time2 = nextMap.time ?? 0; + const value2 = (nextMap.value ?? defaultValue) * scale; + if (keyMap.curve) bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + } + function readTimeline22(timelines, keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = keyMap.time ?? 0; + let value1 = (keyMap[name1] ?? defaultValue) * scale; + let value2 = (keyMap[name2] ?? defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + const nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + timelines.push(timeline); + return; + } + const time2 = nextMap.time ?? 0; + const nvalue1 = (nextMap[name1] ?? defaultValue) * scale; + const nvalue2 = (nextMap[name2] ?? defaultValue) * scale; + const curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + } + function readDrawOrder2(skeletonData, keys, slotCount, folderSlots) { + const changes = keys.offsets; + if (!changes) return null; + const drawOrder = new Array(slotCount).fill(-1); + const unchanged = new Array(slotCount - changes.length); + let originalIndex = 0, unchangedIndex = 0; + for (const offsetMap of changes) { + const slot = skeletonData.findSlot(offsetMap.slot); + if (slot == null) throw new Error(`Draw order slot not found: ${offsetMap.slot}`); + let index = 0; + if (!folderSlots) + index = slot.index; + else { + index = -1; + for (let i = 0; i < slotCount; i++) { + if (folderSlots[i] === slot.index) { + index = i; + break; + } + } + if (index === -1) throw new Error(`Slot not in folder: ${offsetMap.slot}`); + } + while (originalIndex !== index) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] === -1) drawOrder[i] = unchanged[--unchangedIndex]; + return drawOrder; + } + function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve === "stepped") { + timeline.setStepped(frame); + return bezier; + } + const i = value << 2; + const cx1 = curve[i]; + const cy1 = curve[i + 1] * scale; + const cx2 = curve[i + 2]; + const cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; + } + function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; + } + + // spine-core/src/SkeletonPhysicsMovement.ts + var SkeletonPhysicsMovement = class { + /** + * Creates a movement tracker for a skeleton displayed by a host runtime object. + * @param skeleton The skeleton whose physics constraints receive inherited movement. + * @param adapter Runtime-specific hooks used to read and convert the host object's transform. + * @param options Initial movement inheritance values. + */ + constructor(skeleton, adapter, options = {}) { + this.skeleton = skeleton; + this.adapter = adapter; + this.positionInheritanceFactorX = options.positionInheritanceX ?? 0; + this.positionInheritanceFactorY = options.positionInheritanceY ?? 0; + this.rotationInheritanceFactor = options.rotationInheritance ?? 0; + } + positionInheritanceFactorX = 0; + positionInheritanceFactorY = 0; + rotationInheritanceFactor = 0; + hasLastTransform = false; + lastX = 0; + lastY = 0; + lastZ = 0; + lastRotation = 0; + currentTransform = { x: 0, y: 0, z: 0, rotation: 0 }; + currentPosition = { x: 0, y: 0, z: 0 }; + lastPosition = { x: 0, y: 0, z: 0 }; + /** Horizontal position inheritance factor. `0` disables horizontal position inheritance. */ + get positionInheritanceX() { + return this.positionInheritanceFactorX; + } + /** Vertical position inheritance factor. `0` disables vertical position inheritance. */ + get positionInheritanceY() { + return this.positionInheritanceFactorY; + } + /** + * Sets how much host object translation is inherited by skeleton physics constraints. + * Use `(1, 1)` for normal inheritance, or `(0, 0)` to disable position inheritance. + * @param x The horizontal position inheritance factor. + * @param y The vertical position inheritance factor. + */ + setPositionInheritance(x, y) { + const wasDisabled = this.positionInheritanceFactorX === 0 && this.positionInheritanceFactorY === 0; + const isEnabled = x !== 0 || y !== 0; + this.positionInheritanceFactorX = x; + this.positionInheritanceFactorY = y; + if (wasDisabled && isEnabled) this.resetPosition(); + } + /** Rotation inheritance factor. `0` disables rotation inheritance. */ + get rotationInheritance() { + return this.rotationInheritanceFactor; + } + /** + * Sets how much host object rotation is inherited by skeleton physics constraints. + * @param value The rotation inheritance factor. + */ + set rotationInheritance(value) { + const wasDisabled = this.rotationInheritanceFactor === 0; + this.rotationInheritanceFactor = value; + if (wasDisabled && value !== 0) this.resetRotation(); + } + /** Resets the previous position used to calculate inherited translation. */ + resetPosition() { + const transform = this.currentTransform; + const readRotation = !this.hasLastTransform && this.rotationInheritanceFactor !== 0; + this.adapter.readTransform(transform, readRotation); + this.lastX = transform.x; + this.lastY = transform.y; + this.lastZ = transform.z; + if (readRotation) this.lastRotation = transform.rotation; + this.hasLastTransform = true; + } + /** Resets the previous rotation used to calculate inherited rotation. */ + resetRotation() { + const transform = this.currentTransform; + this.adapter.readTransform(transform, true); + this.lastRotation = transform.rotation; + if (!this.hasLastTransform) { + this.lastX = transform.x; + this.lastY = transform.y; + this.lastZ = transform.z; + } + this.hasLastTransform = true; + } + /** Resets both previous position and previous rotation. */ + resetTransform() { + const transform = this.currentTransform; + this.adapter.readTransform(transform, true); + this.setLastTransform(transform.x, transform.y, transform.z, transform.rotation); + } + /** + * Applies host object transform movement since the previous call to the skeleton's physics constraints. + * + * The first call records the current transform as the baseline and does not apply movement. + */ + applyTransformMovement() { + const inheritPosition = this.positionInheritanceFactorX !== 0 || this.positionInheritanceFactorY !== 0; + const inheritRotation = this.rotationInheritanceFactor !== 0; + if (!inheritPosition && !inheritRotation) return; + const transform = this.currentTransform; + this.adapter.readTransform(transform, inheritRotation); + const { x, y, z } = transform; + const currentRotation = inheritRotation ? transform.rotation : this.lastRotation; + const positionChanged = x !== this.lastX || y !== this.lastY || z !== this.lastZ; + if (this.hasLastTransform) { + if (!positionChanged && currentRotation === this.lastRotation) return; + if (inheritPosition && positionChanged) this.applyPositionMovement(x, y, z); + if (inheritRotation && currentRotation !== this.lastRotation) this.applyRotationMovement(currentRotation); + } + this.setLastTransform(x, y, z, currentRotation); + } + applyPositionMovement(currentX, currentY, currentZ) { + const currentPosition = this.currentPosition; + currentPosition.x = currentX; + currentPosition.y = currentY; + currentPosition.z = currentZ; + this.adapter.worldToSkeleton(currentPosition); + const lastPosition = this.lastPosition; + lastPosition.x = this.lastX; + lastPosition.y = this.lastY; + lastPosition.z = this.lastZ; + this.adapter.worldToSkeleton(lastPosition); + this.skeleton.physicsTranslate( + (currentPosition.x - lastPosition.x) * this.positionInheritanceFactorX, + (currentPosition.y - lastPosition.y) * this.positionInheritanceFactorY + ); + } + applyRotationMovement(currentRotation) { + const rotationFactor = this.rotationInheritanceFactor; + if (rotationFactor === 0) return; + this.skeleton.physicsRotate(0, 0, this.getRotationDelta(currentRotation, this.lastRotation) * rotationFactor); + } + setLastTransform(x, y, z, rotation) { + this.lastX = x; + this.lastY = y; + this.lastZ = z; + this.lastRotation = rotation; + this.hasLastTransform = true; + } + getRotationDelta(current, previous) { + let delta = current - previous; + delta = (delta + 180) % 360 - 180; + return delta < -180 ? delta + 360 : delta; + } + }; + + // spine-core/src/SkeletonRendererCore.ts + var SkeletonRendererCore = class { + commandPool = new CommandPool(); + worldVertices = new Float32Array(12 * 1024); + quadIndices = new Uint16Array([0, 1, 2, 2, 3, 0]); + clipping = new SkeletonClipping(); + renderCommands = []; + render(skeleton, pma = false, inColor, stride = 2, slotZOffset = 0) { + this.commandPool.reset(); + this.renderCommands.length = 0; + const clipper = this.clipping; + let z = 0; + const drawOrder = skeleton.drawOrder.appliedPose; + for (let i = 0, n = drawOrder.length; i < n; i++) { + const slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEnd(slot); + continue; + } + const pose = slot.appliedPose; + const attachment = pose.attachment; + if (!attachment) { + clipper.clipEnd(slot); + continue; + } + const slotColor = pose.color; + const alpha = slotColor.a; + if (alpha === 0 && !(attachment instanceof ClippingAttachment)) { + clipper.clipEnd(slot); + continue; + } + let vertices; + let verticesCount; + let uvs; + let indices; + let indicesCount; + let attachmentColor; + let texture; + if (attachment instanceof RegionAttachment) { + attachmentColor = attachment.color; + if (attachmentColor.a === 0) { + clipper.clipEnd(slot); + continue; + } + const sequence = attachment.sequence; + const sequenceIndex = sequence.resolveIndex(pose); + attachment.computeWorldVertices(slot, attachment.getOffsets(pose), this.worldVertices, 0, stride); + vertices = this.worldVertices; + verticesCount = 4; + uvs = sequence.getUVs(sequenceIndex); + indices = this.quadIndices; + indicesCount = 6; + texture = sequence.regions[sequenceIndex]?.texture; + } else if (attachment instanceof MeshAttachment) { + attachmentColor = attachment.color; + if (attachmentColor.a === 0) { + clipper.clipEnd(slot); + continue; + } + if (this.worldVertices.length < attachment.worldVerticesLength) + this.worldVertices = new Float32Array(attachment.worldVerticesLength); + attachment.computeWorldVertices(skeleton, slot, 0, attachment.worldVerticesLength, this.worldVertices, 0, stride); + vertices = this.worldVertices; + verticesCount = attachment.worldVerticesLength >> 1; + const sequence = attachment.sequence; + const sequenceIndex = sequence.resolveIndex(pose); + uvs = sequence.getUVs(sequenceIndex); + indices = attachment.triangles; + indicesCount = indices.length; + texture = sequence.regions[sequenceIndex]?.texture; + } else if (attachment instanceof ClippingAttachment) { + clipper.clipEnd(slot); + clipper.clipStart(skeleton, slot, attachment); + continue; + } else { + clipper.clipEnd(slot); + continue; + } + if (!texture) { + clipper.clipEnd(slot); + continue; + } + const skelColor = skeleton.color; + let color, darkColor; + if (pma) { + let a; + if (inColor) { + a = Math.floor(inColor[3] * skelColor.a * slotColor.a * attachmentColor.a * 255); + const r = Math.floor(a * inColor[0] * skelColor.r * slotColor.r * attachmentColor.r); + const g = Math.floor(a * inColor[1] * skelColor.g * slotColor.g * attachmentColor.g); + const b = Math.floor(a * inColor[2] * skelColor.b * slotColor.b * attachmentColor.b); + color = a << 24 | r << 16 | g << 8 | b; + } else { + a = Math.floor(skelColor.a * slotColor.a * attachmentColor.a * 255); + const r = Math.floor(a * skelColor.r * slotColor.r * attachmentColor.r); + const g = Math.floor(a * skelColor.g * slotColor.g * attachmentColor.g); + const b = Math.floor(a * skelColor.b * slotColor.b * attachmentColor.b); + color = a << 24 | r << 16 | g << 8 | b; + } + darkColor = 4278190080; + if (pose.darkColor) { + const { r, g, b } = pose.darkColor; + darkColor = 4278190080 | Math.floor(r * a) << 16 | Math.floor(g * a) << 8 | Math.floor(b * a); + } + } else { + if (inColor) { + const a = Math.floor(inColor[3] * skelColor.a * slotColor.a * attachmentColor.a * 255); + const r = Math.floor(inColor[0] * skelColor.r * slotColor.r * attachmentColor.r * 255); + const g = Math.floor(inColor[1] * skelColor.g * slotColor.g * attachmentColor.g * 255); + const b = Math.floor(inColor[2] * skelColor.b * slotColor.b * attachmentColor.b * 255); + color = a << 24 | r << 16 | g << 8 | b; + } else { + const a = Math.floor(skelColor.a * slotColor.a * attachmentColor.a * 255); + const r = Math.floor(skelColor.r * slotColor.r * attachmentColor.r * 255); + const g = Math.floor(skelColor.g * slotColor.g * attachmentColor.g * 255); + const b = Math.floor(skelColor.b * slotColor.b * attachmentColor.b * 255); + color = a << 24 | r << 16 | g << 8 | b; + } + darkColor = 0; + if (pose.darkColor) { + const { r, g, b } = pose.darkColor; + darkColor = Math.floor(r * 255) << 16 | Math.floor(g * 255) << 8 | Math.floor(b * 255); + } + } + if (clipper.isClipping()) { + clipper.clipTrianglesUnpacked(vertices, 0, indices, indicesCount, uvs, stride); + vertices = clipper.clippedVerticesTyped; + verticesCount = clipper.clippedVerticesLength / stride; + uvs = clipper.clippedUVsTyped; + indices = clipper.clippedTrianglesTyped; + indicesCount = clipper.clippedTrianglesLength; + } + const cmd = this.commandPool.getCommand(verticesCount, indicesCount, stride); + cmd.blendMode = slot.data.blendMode; + cmd.texture = texture; + cmd.positions.set(vertices.subarray(0, verticesCount * stride)); + if (stride >= 3) { + for (let j = 2, n2 = verticesCount * stride; j < n2; j += stride) + cmd.positions[j] = z; + } + cmd.uvs.set(uvs.subarray(0, verticesCount << 1)); + for (let j = 0; j < verticesCount; j++) { + cmd.colors[j] = color; + cmd.darkColors[j] = darkColor; + } + if (indices instanceof Uint16Array) { + cmd.indices.set(indices.subarray(0, indicesCount)); + } else { + cmd.indices.set(indices.slice(0, indicesCount)); + } + this.renderCommands.push(cmd); + z += slotZOffset; + clipper.clipEnd(slot); + } + clipper.clipEnd(); + return this.batchCommands(stride); + } + batchSubCommands(commands, first, last, numVertices, numIndices, stride) { + const firstCmd = commands[first]; + const batched = this.commandPool.getCommand(numVertices, numIndices, stride); + batched.blendMode = firstCmd.blendMode; + batched.texture = firstCmd.texture; + let positionsOffset = 0; + let uvsOffset = 0; + let colorsOffset = 0; + let indicesOffset = 0; + let vertexOffset = 0; + for (let i = first; i <= last; i++) { + const cmd = commands[i]; + batched.positions.set(cmd.positions, positionsOffset); + positionsOffset += cmd.numVertices * stride; + batched.uvs.set(cmd.uvs, uvsOffset); + uvsOffset += cmd.numVertices << 1; + batched.colors.set(cmd.colors, colorsOffset); + batched.darkColors.set(cmd.darkColors, colorsOffset); + colorsOffset += cmd.numVertices; + for (let j = 0; j < cmd.numIndices; j++) + batched.indices[indicesOffset + j] = cmd.indices[j] + vertexOffset; + indicesOffset += cmd.numIndices; + vertexOffset += cmd.numVertices; + } + return batched; + } + batchCommands(stride) { + if (this.renderCommands.length === 0) return void 0; + let root; + let last; + let first = this.renderCommands[0]; + let startIndex = 0; + let i = 1; + let numVertices = first.numVertices; + let numIndices = first.numIndices; + while (i <= this.renderCommands.length) { + const cmd = i < this.renderCommands.length ? this.renderCommands[i] : null; + if (cmd && cmd.numVertices === 0 && cmd.numIndices === 0) { + i++; + continue; + } + const canBatch = cmd !== null && cmd.texture === first.texture && cmd.blendMode === first.blendMode && cmd.colors[0] === first.colors[0] && cmd.darkColors[0] === first.darkColors[0] && numIndices + cmd.numIndices < 65535; + if (canBatch) { + numVertices += cmd.numVertices; + numIndices += cmd.numIndices; + } else { + const batched = this.batchSubCommands( + this.renderCommands, + startIndex, + i - 1, + numVertices, + numIndices, + stride + ); + if (!last) { + root = last = batched; + } else { + last.next = batched; + last = batched; + } + if (i === this.renderCommands.length) break; + first = this.renderCommands[i]; + startIndex = i; + numVertices = first.numVertices; + numIndices = first.numIndices; + } + i++; + } + return root; + } + }; + var CommandPool = class { + pool = []; + inUse = []; + getCommand(numVertices, numIndices, stride) { + let cmd; + for (const c of this.pool) { + if (c._positions.length >= numVertices * stride && c._indices.length >= numIndices) { + cmd = c; + break; + } + } + if (!cmd) { + const _positions = new Float32Array(numVertices * stride); + const _uvs = new Float32Array(numVertices << 1); + const _colors = new Uint32Array(numVertices); + const _darkColors = new Uint32Array(numVertices); + const _indices = new Uint16Array(numIndices); + cmd = { + positions: _positions, + uvs: _uvs, + colors: _colors, + darkColors: _darkColors, + indices: _indices, + _positions, + _uvs, + _colors, + _darkColors, + _indices, + numVertices, + numIndices, + blendMode: 0 /* Normal */, + texture: null + }; + } else { + this.pool.splice(this.pool.indexOf(cmd), 1); + cmd.next = void 0; + cmd.numVertices = numVertices; + cmd.numIndices = numIndices; + cmd.positions = cmd._positions.subarray(0, numVertices * stride); + cmd.uvs = cmd._uvs.subarray(0, numVertices << 1); + cmd.colors = cmd._colors.subarray(0, numVertices); + cmd.darkColors = cmd._darkColors.subarray(0, numVertices); + cmd.indices = cmd._indices.subarray(0, numIndices); + } + this.inUse.push(cmd); + return cmd; + } + reset() { + this.pool.push(...this.inUse); + this.inUse.length = 0; + } + }; + + // spine-canvas/src/CanvasTexture.ts + var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-canvas/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new CanvasTexture(image); + }, pathPrefix, downloader); + } + }; + + // spine-canvas/src/SkeletonRenderer.ts + var worldVertices = Utils.newFloatArray(8); + var SkeletonRenderer = class _SkeletonRenderer { + static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + static VERTEX_SIZE = 2 + 2 + 4; + ctx; + triangleRendering = false; + debugRendering = false; + vertices = Utils.newFloatArray(8 * 1024); + tempColor = new Color(); + constructor(context) { + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) this.drawTriangles(skeleton); + else this.drawImages(skeleton); + } + drawImages(skeleton) { + const ctx = this.ctx; + const color = this.tempColor; + const skeletonColor = skeleton.color; + const drawOrder = skeleton.drawOrder.appliedPose; + if (this.debugRendering) ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + const slot = drawOrder[i]; + const bone = slot.bone; + if (!bone.active) continue; + const pose = slot.appliedPose; + const attachment = pose.attachment; + if (!(attachment instanceof RegionAttachment)) continue; + const sequence = attachment.sequence; + const sequenceIndex = sequence.resolveIndex(pose); + attachment.computeWorldVertices(slot, attachment.getOffsets(pose), worldVertices, 0, 2); + const region = sequence.regions[sequenceIndex]; + const image = region.texture.getImage(); + 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, + skeletonColor.a * slotColor.a * regionColor.a + ); + ctx.save(); + const boneApplied = bone.appliedPose; + ctx.transform(boneApplied.a, boneApplied.c, boneApplied.b, boneApplied.d, boneApplied.worldX, boneApplied.worldY); + const offsets = attachment.getOffsets(pose); + ctx.translate(offsets[0], offsets[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + 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 (region.degrees === 90) { + const t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h); + if (this.debugRendering) ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + const ctx = this.ctx; + const color = this.tempColor; + const skeletonColor = skeleton.color; + const drawOrder = skeleton.drawOrder.appliedPose; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + const slot = drawOrder[i]; + const pose = slot.appliedPose; + const attachment = pose.attachment; + let texture; + if (attachment instanceof RegionAttachment) { + const sequence = attachment.sequence; + const sequenceIndex = sequence.resolveIndex(pose); + const uvs = sequence.getUVs(sequenceIndex); + const offsets = attachment.getOffsets(pose); + vertices = this.computeRegionVertices(slot, attachment, offsets, uvs, false); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + texture = (sequence.regions[sequenceIndex]?.texture).getImage(); + } else if (attachment instanceof MeshAttachment) { + const sequence = attachment.sequence; + const sequenceIndex = sequence.resolveIndex(pose); + const uvs = sequence.getUVs(sequenceIndex); + vertices = this.computeMeshVertices(slot, attachment, uvs, false); + triangles = attachment.triangles; + texture = (sequence.regions[sequenceIndex]?.texture).getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode !== blendMode) blendMode = slot.data.blendMode; + 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, + skeletonColor.a * slotColor.a * attachmentColor.a + ); + ctx.globalAlpha = color.a; + for (let j = 0; j < triangles.length; j += 3) { + const t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + 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); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + // Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 + // Apache 2 licensed + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + const ctx = this.ctx; + const width = img.width - 1; + const height = img.height - 1; + u0 *= width; + v0 *= height; + u1 *= width; + v1 *= height; + u2 *= width; + v2 *= height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + let det = u1 * v2 - u2 * v1; + if (det === 0) return; + det = 1 / det; + const a = (v2 * x1 - v1 * x2) * det; + const b = (v2 * y1 - v1 * y2) * det; + const c = (u1 * x2 - u2 * x1) * det; + const d = (u1 * y2 - u2 * y1) * det; + const e = x0 - a * u0 - c * v0; + const f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, offsets, uvs, pma) { + const skeletonColor = slot.skeleton.color; + const slotColor = slot.appliedPose.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, + alpha + ); + region.computeWorldVertices(slot, offsets, this.vertices, 0, _SkeletonRenderer.VERTEX_SIZE); + const vertices = this.vertices; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, uvs, pma) { + const skeleton = slot.skeleton; + const skeletonColor = skeleton.color; + const slotColor = slot.appliedPose.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 + ); + 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); + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } + }; + return __toCommonJS(index_exports); +})(); +//# sourceMappingURL=spine-canvas.js.map diff --git a/release/MAC版本/logo-spineviewer.png b/release/MAC版本/logo-spineviewer.png new file mode 100644 index 0000000..4ef2ca1 Binary files /dev/null and b/release/MAC版本/logo-spineviewer.png differ diff --git a/release/MAC版本/manifest.json b/release/MAC版本/manifest.json new file mode 100644 index 0000000..ddc3729 --- /dev/null +++ b/release/MAC版本/manifest.json @@ -0,0 +1,28 @@ +{ + "id": "f6602400-1327-485c-98e0-78ae9fded460", + "version": "1.1.0", + "platform": "all", + "arch": "all", + "name": "SpineViewer", + "logo": "/logo-spineviewer.png", + "keywords": [ + "spine", + "骨骼动画", + "动画预览", + "skel", + "atlas" + ], + "devTools": false, + "preview": { + "skel,skel.bytes,bytes,json,atlas,atlas.txt,txt": { + "thumbnail": { + "path": "thumbnail/spine.js", + "size": 400, + "allowZoom": false + }, + "viewer": { + "path": "viewer/spine.html" + } + } + } +} diff --git a/release/MAC版本/package-lock.json b/release/MAC版本/package-lock.json new file mode 100644 index 0000000..4c39091 --- /dev/null +++ b/release/MAC版本/package-lock.json @@ -0,0 +1,212 @@ +{ + "name": "spineviewer", + "version": "1.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "spineviewer", + "version": "1.1.0", + "license": "ISC", + "dependencies": { + "@napi-rs/canvas": "^0.1.66" + } + }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.66.tgz", + "integrity": "sha512-NE/eQKLbUS+LCbMHRa5HnR7cc1Q4ibg/qfLUN4Ukl3CC0lq6LfHE0YbvFm/l4i5RyyS+aUjL+8IuZDD9EH3amg==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.66", + "@napi-rs/canvas-darwin-arm64": "0.1.66", + "@napi-rs/canvas-darwin-x64": "0.1.66", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.66", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.66", + "@napi-rs/canvas-linux-arm64-musl": "0.1.66", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.66", + "@napi-rs/canvas-linux-x64-gnu": "0.1.66", + "@napi-rs/canvas-linux-x64-musl": "0.1.66", + "@napi-rs/canvas-win32-x64-msvc": "0.1.66" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.66.tgz", + "integrity": "sha512-77Yq9yaUYN90zCovYOpw7LhidJiswU9wLIWWBGF6iiEJyQdt6tkiXpGRZpOMJVO70afkcdc4T7532cxMIBhk0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.66.tgz", + "integrity": "sha512-cz3aJ06b8BZGtwRxKTiE0OVUlB17MH8j+BnE4A5+wD9aD1guCCqECsz+k7tpXdAdTAYKRIz2pq6ZuiJ76NyUbQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.66.tgz", + "integrity": "sha512-szIWqJgFm2OTyGzM+hSiJOaOtjI73VYRC2KN30zZTt7i1+0sgpm5exK5ltDBPOmCdnLt7SbUfpInLj8VvxYlKA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.66.tgz", + "integrity": "sha512-h/TZJFc6JLvp8FwbA5mu+yXiblN0iKqshU7xzd6L+ks5uNYgjS7XWLkNiyPQkMaXQgVczOJfZy7r4NSPK3V8Hg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.66.tgz", + "integrity": "sha512-RGFUdBdi0Xmf+TfwZcB89Ap6hDYh4nzyJhXhNJIgve6ELrIPFhf7sDHvUHxjgW0YzczGoo+ophyCm03cJggu+w==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.66.tgz", + "integrity": "sha512-2cFViDIZ0xQlAHyJmyym+rj3p04V16vgAiz64sCAfwOOiW6e19agv1HQWHUsro3G2lF3PaHGAnp0WRPXGqLOfg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.66.tgz", + "integrity": "sha512-Vm5ZWS2RDPeBpnfx83eJpZfJT07xl0jqp8d83PklKqiDNa3BmDZZ/uuI40/ICgejGLymXXYo5N21b7oAxhRTSA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.66.tgz", + "integrity": "sha512-/ptGBhErNBCgWff3khtuEjhiiYWf70oWvBPRj8y5EMB0nLYpve7RxxFnavVvxN49kJ0MQHRIwgfyd47RSOOKPw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.66.tgz", + "integrity": "sha512-XunvXisTkIG+bpq6BcXmsUstoLX3RLS6N9Uz9Pg9RpWIMeM6ObR5shr3NgpGRJq93769I1hS4mJW0DX2Au3WBw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.66.tgz", + "integrity": "sha512-3n34watNFqpwACDA+pt4jfQD6zR8PzfK86FBajdsgDVVZhSp6ohgbbJv+eUrXM08VUtjxTq7+U4sWspTu9+4Ug==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/release/MAC版本/package.json b/release/MAC版本/package.json new file mode 100644 index 0000000..a1ddf03 --- /dev/null +++ b/release/MAC版本/package.json @@ -0,0 +1,11 @@ +{ + "name": "spineviewer", + "version": "1.1.0", + "description": "Eagle 插件:离线预览 Spine 导出的骨骼动画(skel / skel.bytes / json / atlas / atlas.txt / png / jpg / jpeg / webp)", + "main": "thumbnail/spine.js", + "private": true, + "type": "commonjs", + "dependencies": { + "@napi-rs/canvas": "^0.1.66" + } +} diff --git a/release/MAC版本/thumbnail/spine.js b/release/MAC版本/thumbnail/spine.js new file mode 100644 index 0000000..03a717c --- /dev/null +++ b/release/MAC版本/thumbnail/spine.js @@ -0,0 +1,585 @@ +const fs = require('fs'); +const path = require('path'); +const os = require('os'); +const http = require('http'); +const crypto = require('crypto'); +const zlib = require('zlib'); +const utils = require('./../js/spine-utils.js'); +const render = require('./../js/spine-render.js'); + +/** 简易日志(写入插件目录 thumbnails.log,便于诊断 Eagle 中的间歇失败) */ +function log(msg) { + try { + const logPath = path.join(__dirname, '..', 'thumbnails.log'); + fs.appendFileSync(logPath, '[' + new Date().toISOString() + '] ' + msg + '\n'); + } catch (e) { /* ignore */ } +} + +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); +const discoveryJobs = new Map(); +const renderJobs = new Map(); +const refreshJobs = new Map(); + +/** 插件代码版本:每次改动递增,用于确认 Eagle 是否加载到最新代码 */ +const VERSION = 'v14'; + +function coordinationKey(src) { + const root = utils.findLibraryRoot(src) || path.dirname(path.dirname(src)); + const folders = utils.foldersOfItem(src).slice().sort().join(',') || 'unfiled'; + return root + '|' + folders + '|' + utils.normalizeStem(path.basename(src)); +} + +/** 返回资源当前的尺寸/修改时间签名,同时确认 atlas 引用的全部贴图均已落盘。 */ +function assetSignature(assets) { + if (!assets || !assets.skeletonPath || !assets.atlasPath) return null; + let atlasText = ''; + try { atlasText = fs.readFileSync(assets.atlasPath, 'utf8'); } catch (e) { return null; } + const pages = utils.parseAtlasPages(atlasText); + if (pages.length === 0 || pages.some((name) => !assets.texturePaths[name])) return null; + const paths = [assets.skeletonPath, assets.atlasPath].concat(pages.map((name) => assets.texturePaths[name])); + const stats = []; + for (const file of paths) { + try { + const stat = fs.statSync(file); + if (!stat.isFile() || stat.size === 0) return null; + stats.push(file + ':' + stat.size + ':' + Math.round(stat.mtimeMs)); + } catch (e) { + return null; + } + } + return stats.join('|'); +} + +/** + * Eagle 拖入一组文件时会并发触发 atlas/json/skel 的缩略图回调,而文件内容和 + * folders 元数据仍可能继续写入。等同批资源连续三次保持不变后再渲染,避免把 + * 半截 atlas 或旧库中的同名骨骼渲染成占位图。 + */ +async function runDiscovery(src, retries, delay) { + let assets = null; + let previousSignature = null; + let stableCount = 0; + for (let i = 0; i < retries; i++) { + // 前台缩略图回调只接受同批资源,绝不借用库里旧的同名 atlas/贴图。 + // 分批拖入的跨批次补齐统一交给后台任务处理。 + assets = utils.discoverAssets(src, { + strictStem: true, + allowCrossBatch: false, + refreshIndex: i > 0, + }); + const signature = assetSignature(assets); + if (signature && signature === previousSignature) stableCount += 1; + else stableCount = signature ? 1 : 0; + previousSignature = signature; + if (stableCount >= 3) return assets; + if (i < retries - 1) await sleep(delay); + } + return assets; +} + +/** 同一资源组的 atlas/json/skel 回调共享发现任务,避免大批量导入时重复全库扫描。 */ +async function discoverWithRetry(src, retries = 5, delay = 120) { + const key = coordinationKey(src); + if (discoveryJobs.has(key)) return discoveryJobs.get(key); + const job = runDiscovery(src, retries, delay); + discoveryJobs.set(key, job); + try { + return await job; + } finally { + if (discoveryJobs.get(key) === job) discoveryJobs.delete(key); + } +} + +/** JSON 仍在落盘时只做极短等待;普通 JSON 一经确认便立即退出 Spine 流程。 */ +async function classifyJsonBriefly(src) { + let kind = 'pending'; + for (let i = 0; i < 3; i++) { + kind = utils.classifySkeletonJson(src); + if (kind !== 'pending') return kind; + if (i < 2) await sleep(80); + } + return kind; +} + +/** 同一份稳定资源只渲染一次,atlas/json/skel 并发回调共享输出 Buffer。 */ +async function renderThumbnailShared(assets, options) { + const key = assetSignature(assets) + '|' + options.version + '|' + options.runtimeDir + '|' + options.size; + if (renderJobs.has(key)) { + log('复用同组渲染结果: ' + (assets.base || path.basename(options.skeletonPath))); + return renderJobs.get(key); + } + log('开始同组统一渲染: ' + (assets.base || path.basename(options.skeletonPath))); + const job = render.renderThumbnail(options); + renderJobs.set(key, job); + try { + return await job; + } finally { + setTimeout(() => { if (renderJobs.get(key) === job) renderJobs.delete(key); }, 2000); + } +} + +/** + * Eagle 格式扩展缩略图处理函数。 + * 参数:{ src, dest, item } + * - src : 原始文件路径(skel/skel.bytes/json/atlas/atlas.txt) + * - dest : 需要生成的缩略图 PNG 路径 + * - item : 当前 item 对象(可更新宽高) + */ +module.exports = async (options) => { + const { src, dest, item } = options; + const changed = require('../js/eagle-compound.js').normalizeItem(src, item); + // Eagle originally chooses the cache name before invoking the plugin. + // Supply that requested output as well as the corrected compound-name cache. + const canonical = changed && path.basename(dest).endsWith('_thumbnail.png') + ? path.join(path.dirname(dest), item.name + '_thumbnail.png') : dest; + const result = await generate({ ...options, deferRefresh: changed }); + if (canonical !== dest && fs.existsSync(dest)) { + if (render.canvasLib) { + const image = await render.canvasLib.loadImage(dest); + const canvas = render.canvasLib.createCanvas(image.width, image.height); + canvas.getContext('2d').drawImage(image, 0, 0); + fs.writeFileSync(canonical, await canvas.encode('webp', 90)); + } else fs.copyFileSync(dest, canonical); + } + if (changed && item.id) { + log('复合后缀元数据已规范化: name=' + item.name + ' ext=' + item.ext); + } + const ext = utils.extOf(path.basename(src)); + if (!item.isDeleted && (utils.isAtlasFile(src) || (utils.isSkeletonFile(src) && (ext !== '.json' || utils.classifySkeletonJson(src) === 'spine')))) scheduleBackgroundReconcile(src); + return result; +}; + +async function generate({ src, dest, item, deferRefresh }) { + try { + // 记录 Eagle 传入的关键信息,便于诊断 src/item 的实际形态 + log('HIT ' + VERSION + ' src=' + src + ' (isTexture=' + utils.isTextureFile(src) + ')'); + try { + log(' item keys=' + Object.keys(item || {}).join(',') + ' | name=' + (item && item.name) + ' | id=' + (item && item.id) + ' | ext=' + (item && item.ext) + ' | isDeleted=' + (item && item.isDeleted)); + } catch (e) { /* ignore */ } + + // —— 守护:若 src 文件在库中不存在(可能是回收站 isDeleted 残留 / 临时 id), + // 且 item 标记为已删除,则跳过,避免生成破碎/占位缩略图,交由 Eagle 自身处理。 + if (item && item.isDeleted) { + log(' skip: item.isDeleted=true'); + return resolve(item); + } + + // —— 防御:若 src 是图片(png/jpg/jpeg/webp),不生成占位图, + // 而是把原始图片复制/转换为缩略图,交由系统展示真实内容。 + const srcExt = utils.extOf(path.basename(src)); + // Eagle dispatches compound suffixes as txt/bytes. Only the complete + // .atlas.txt/.skel.bytes names enter Spine discovery; ordinary files exit. + if (!srcExt) { + if (/\.txt$/i.test(src)) { + // Eagle's native text card requires item.text, even for an empty file. + item.text = ''; + const fd = fs.openSync(src, 'r'); + try { const buffer = Buffer.alloc(32768); item.text = buffer.subarray(0, fs.readSync(fd, buffer, 0, buffer.length, 0)).toString('utf8'); } + finally { fs.closeSync(fd); } + } + await writeNeutralJsonPlaceholder(dest); + item.width = 400; item.height = 400; + return resolve(item); + } + if (utils.isTextureFile(src) || srcExt === '.png' || srcExt === '.jpg' || srcExt === '.jpeg' || srcExt === '.webp') { + await copyImageAsThumb(src, dest); + try { const s = imageSizeOf(dest); item.width = s.width || item.width; item.height = s.height || item.height; } catch (e) {} + return resolve(item); + } + + // manifest 只能按扩展名接管 JSON,不能按文件内容过滤。因此先做低成本内容判定: + // 普通 JSON 不写 dest,不修改尺寸,也不启动资源扫描和后台补刷。 + // 这样可以保留 Eagle 或其他 JSON 插件生成的缩略图,避免本插件的回退图覆盖它。 + if (srcExt === '.json') { + const jsonKind = await classifyJsonBriefly(src); + if (jsonKind === 'other') { + log('普通 JSON,放行给 Eagle/其他 JSON 插件: ' + src); + return resolve(item); + } + } + + let assets = await discoverWithRetry(src); + + // 找不到完整 Spine 资源链(骨骼 + atlas + atlas 引用的全部贴图) + if (!assets.skeletonPath || !assets.atlasPath || !assetSignature(assets)) { + log('未找到配套资源: ' + src + ' (skeleton=' + !!assets.skeletonPath + ', atlas=' + !!assets.atlasPath + ')'); + if (assets.atlasPath && await writeAtlasFallback(assets, dest)) { + item.width = 400; item.height = 400; + return resolve(item); + } + await writePlaceholder(dest); + item.width = 400; item.height = 400; + return resolve(item); + } + + let version = utils.detectVersion(assets.skeletonPath); + let runtimeDir = utils.chooseRuntimeDir(version, assets.isBinary); + + if (!runtimeDir) { + if (await writeAtlasFallback(assets, dest)) { + if (!deferRefresh) await refreshRelatedThumbnails(assets, dest, item && item.id); + item.width = 400; item.height = 400; + return resolve(item); + } + await writePlaceholder(dest); + item.width = 400; item.height = 400; + return resolve(item); + } + + // 渲染首帧到 PNG。若导入过程恰好仍在写大文件,重新发现稳定资源再试, + // 每次都会重新匹配同批 atlas/json/skel,而不是重复读取原来的错误组合。 + let png = null; + let lastRenderError = null; + for (let attempt = 0; attempt < 3; attempt++) { + try { + png = await renderThumbnailShared(assets, { + skeletonPath: assets.skeletonPath, + atlasPath: assets.atlasPath, + texturePaths: assets.texturePaths, + version, + runtimeDir, + size: 400, + }); + break; + } catch (e) { + lastRenderError = e; + log('renderThumbnail 第 ' + (attempt + 1) + ' 次失败: ' + (e && e.message) + ',重新等待同批资源...'); + if (attempt === 2) break; + await sleep(500); + assets = await discoverWithRetry(src, 4, 150); + if (!assets.skeletonPath || !assets.atlasPath || !assetSignature(assets)) continue; + version = utils.detectVersion(assets.skeletonPath); + runtimeDir = utils.chooseRuntimeDir(version, assets.isBinary); + } + } + if (!png) { + if (await writeAtlasFallback(assets, dest)) { + log('骨骼无法解析,已使用 atlas 贴图缩略图: ' + src); + if (!deferRefresh) await refreshRelatedThumbnails(assets, dest, item && item.id); + item.width = 400; item.height = 400; + return resolve(item); + } + throw lastRenderError || new Error('Spine 资源尚未写入完成'); + } + + fs.writeFileSync(dest, png); + if (!deferRefresh) await refreshRelatedThumbnails(assets, dest, item && item.id); + + try { + const size = imageSizeOf(dest); + item.width = size.width || 400; + item.height = size.height || 400; + } catch (e) { /* ignore */ } + + return Promise.resolve(item); + } catch (err) { + // 兜底:总是生成一张有效 PNG,绝不 reject,避免 Eagle 显示默认图标 + log('缩略图处理异常: ' + (err && err.message) + '\n' + ((err && err.stack) || '')); + try { + await writePlaceholder(dest); + item.width = 400; + item.height = 400; + return resolve(item); + } catch (e2) { + // 最后兜底:写入一张最小 1x1 PNG + try { fs.writeFileSync(dest, Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+M8AAAMBAQDJ/pLvAAAAAElFTkSuQmCC', 'base64')); } catch (e3) {} + item.width = 400; item.height = 400; + return resolve(item); + } + } +}; + +function resolve(item) { + return item; +} + +function itemIdFromAssetPath(filePath) { + const match = path.basename(path.dirname(filePath)).match(/^(.+)\.info$/i); + return match ? match[1] : null; +} + +async function setEagleCustomThumbnail(itemId, thumbnailPath, expectedFilename) { + if (expectedFilename) { + // Eagle's foreground may still hold the old name after a type change. + // Do not let setCustomThumbnail persist that stale name back to metadata. + const info = await new Promise((resolveInfo, rejectInfo) => { + const req = http.get('http://127.0.0.1:41595/api/item/info?id=' + encodeURIComponent(itemId), response => { + let body = ''; response.on('data', chunk => { body += chunk; }); + response.on('end', () => { + try { const result = JSON.parse(body); if (result.status !== 'success') throw new Error('Eagle 素材尚未入库'); resolveInfo(result.data); } + catch (error) { rejectInfo(error); } + }); + }); + req.setTimeout(3000, () => req.destroy(new Error('Eagle 素材信息请求超时'))); req.on('error', rejectInfo); + }); + if (!info || info.name + '.' + info.ext !== expectedFilename) throw new Error('Eagle 尚未同步复合后缀名称,请重新打开素材库后刷新缩略图'); + } + return new Promise((resolveRequest, rejectRequest) => { + const body = JSON.stringify({ id: itemId, thumbnailPath }); + const request = http.request({ + hostname: '127.0.0.1', + port: 41595, + path: '/api/item/setCustomThumbnail', + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, + }, (response) => { + let data = ''; + response.on('data', (chunk) => { data += chunk; }); + response.on('end', () => { + if (response.statusCode >= 200 && response.statusCode < 300) resolveRequest(data); + else rejectRequest(new Error('Eagle API HTTP ' + response.statusCode + ': ' + data)); + }); + }); + request.on('error', rejectRequest); + request.setTimeout(12000, () => request.destroy(new Error('Eagle 缩略图请求超时'))); + request.end(body); + }); +} + +async function createWebpCopy(sourcePath, key) { + if (!render.canvasLib) return sourcePath; + const image = await render.canvasLib.loadImage(sourcePath); + const canvas = render.canvasLib.createCanvas(image.width, image.height); + canvas.getContext('2d').drawImage(image, 0, 0); + const unique = crypto.randomBytes(8).toString('hex'); + const output = path.join(os.tmpdir(), 'spineviewer-' + process.pid + '-' + Date.now() + '-' + unique + '-' + key.replace(/[^a-z0-9]/gi, '') + '.webp'); + fs.writeFileSync(output, await canvas.encode('webp', 90)); + return output; +} + +/** 将一份已验证的缩略图主动应用到同一资源链的 atlas/json/skel 条目。 */ +async function refreshRelatedThumbnails(assets, thumbnailPath, currentItemId) { + const signature = assetSignature(assets); + if (!signature) return false; + const ids = [...new Set((assets.relatedDataPaths || []).map(itemIdFromAssetPath).concat(currentItemId || []).filter(Boolean))]; + if (ids.length === 0) return true; + const key = signature + '|' + ids.slice().sort().join(','); + if (refreshJobs.has(key)) return refreshJobs.get(key); + const job = (async () => { + let apiPath = thumbnailPath; + try { + apiPath = await createWebpCopy(thumbnailPath, utils.normalizeStem(path.basename(assets.skeletonPath || assets.atlasPath))); + const results = await Promise.allSettled(ids.map((id) => { + const source = (assets.relatedDataPaths || []).find(file => itemIdFromAssetPath(file) === id); + return setEagleCustomThumbnail(id, apiPath, source && path.basename(source)); + })); + const failed = results.filter((result) => result.status === 'rejected'); + if (failed.length) throw failed[0].reason; + log('统一补刷完成: ' + ids.length + ' 个条目 [' + ids.join(',') + ']'); + return true; + } catch (e) { + log('统一补刷失败: ' + ((e && e.message) || String(e))); + return false; + } finally { + if (apiPath !== thumbnailPath) { + try { fs.unlinkSync(apiPath); } catch (e) { /* ignore */ } + } + } + })(); + refreshJobs.set(key, job); + try { + return await job; + } finally { + setTimeout(() => { if (refreshJobs.get(key) === job) refreshJobs.delete(key); }, 2000); + } +} + +/** + * 资源暂不完整时在后台继续观察。贴图最后落盘不会触发格式扩展回调,因此这里负责 + * 在链路补齐后渲染一次,并统一刷新此前已生成占位图的所有数据条目。 + */ +function scheduleBackgroundReconcile(src) { + try { require('../js/spine-reconcile-worker.js').enqueue(src); } + catch (error) { log('无法启动后台补刷: ' + String(error)); } +} + +// Called by a separate Node worker; Eagle closes the thumbnail window when +// its callback resolves, so timers in that window cannot finish this work. +module.exports.reconcileOnce = async (src, previousSignature) => { + if (!fs.existsSync(src) || utils.isItemDeleted(src)) return { complete: true }; + const assets = utils.discoverAssets(src, { strictStem: true, allowCrossBatch: true, refreshIndex: true }); + const signature = assetSignature(assets); + if (!signature || signature !== previousSignature) return { signature, complete: false }; + const version = utils.detectVersion(assets.skeletonPath); + const runtimeDir = utils.chooseRuntimeDir(version, assets.isBinary); + if (!runtimeDir) return { signature, complete: true }; + const temp = path.join(os.tmpdir(), 'spineviewer-reconcile-' + crypto.randomBytes(12).toString('hex') + '.png'); + try { + const png = await renderThumbnailShared(assets, { ...assets, version, runtimeDir, size: 400 }); + fs.writeFileSync(temp, png); + const complete = await refreshRelatedThumbnails(assets, temp); + return { signature, complete }; + } catch (error) { + log('后台补刷重试: ' + String(error)); + return { signature, complete: false }; + } finally { try { fs.unlinkSync(temp); } catch (error) { if (error.code !== 'ENOENT') log(String(error)); } } +}; + +/** 普通 JSON 使用中性文件图形,避免错误显示 Spine badge。 */ +async function writeNeutralJsonPlaceholder(dest) { + const size = 400; + if (render.canvasLib) { + try { + const canvas = render.canvasLib.createCanvas(size, size); + const ctx = canvas.getContext('2d'); + ctx.fillStyle = '#202126'; + ctx.fillRect(0, 0, size, size); + ctx.fillStyle = '#555963'; + ctx.beginPath(); + ctx.moveTo(112, 72); + ctx.lineTo(244, 72); + ctx.lineTo(288, 116); + ctx.lineTo(288, 328); + ctx.lineTo(112, 328); + ctx.closePath(); + ctx.fill(); + ctx.fillStyle = '#777c87'; + ctx.beginPath(); + ctx.moveTo(244, 72); + ctx.lineTo(244, 116); + ctx.lineTo(288, 116); + ctx.closePath(); + ctx.fill(); + fs.writeFileSync(dest, canvas.toBuffer('image/png')); + return; + } catch (e) { /* fall through */ } + } + const pixels = Buffer.alloc(size * size * 4); + for (let i = 0; i < pixels.length; i += 4) { + pixels[i] = 32; pixels[i + 1] = 33; pixels[i + 2] = 38; pixels[i + 3] = 255; + } + fs.writeFileSync(dest, encodePng(size, size, pixels)); +} + +/** 将任意图片作为缩略图复制/转换为 PNG(PNG 直接拷贝,JPG/WebP 用 @napi-rs/canvas 转换) */ +async function copyImageAsThumb(src, dest) { + const ext = path.extname(src).toLowerCase(); + if (ext === '.png') { + fs.copyFileSync(src, dest); + return; + } + if (render.canvasLib) { + try { + const img = await render.canvasLib.loadImage(src); + const w = img.width, h = img.height; + const canvas = render.canvasLib.createCanvas(w, h); + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, w, h); + fs.writeFileSync(dest, canvas.toBuffer('image/png')); + return; + } catch (e) { /* fall through */ } + } + fs.copyFileSync(src, dest); +} + +/** 骨骼二进制无法解析时,用真实 atlas 贴图生成可辨认的回退缩略图。 */ +async function writeAtlasFallback(assets, dest) { + if (!render.canvasLib || !assets || !assets.texturePaths) return false; + const texturePath = Object.values(assets.texturePaths).find((file) => { + try { return fs.statSync(file).size > 0; } catch (e) { return false; } + }); + if (!texturePath) return false; + try { + const img = await render.canvasLib.loadImage(texturePath); + const size = 400; + const canvas = render.canvasLib.createCanvas(size, size); + const ctx = canvas.getContext('2d'); + ctx.fillStyle = '#1e1e22'; + ctx.fillRect(0, 0, size, size); + const scale = Math.min((size - 24) / img.width, (size - 24) / img.height); + const w = Math.max(1, Math.round(img.width * scale)); + const h = Math.max(1, Math.round(img.height * scale)); + ctx.drawImage(img, Math.round((size - w) / 2), Math.round((size - h) / 2), w, h); + await render.drawSpineBadge(ctx, size, size); + if (assets.skeletonPath) require('../js/spine-badge.js').drawVersion(ctx, size, size, utils.detectVersion(assets.skeletonPath)); + fs.writeFileSync(dest, canvas.toBuffer('image/png')); + return true; + } catch (e) { + log('atlas 贴图回退失败: ' + (e && e.message)); + return false; + } +} + +/** 读取 PNG 宽高(仅支持 PNG 头部) */ +function imageSizeOf(file) { + const buf = fs.readFileSync(file); + if (buf.slice(0, 8).toString('hex') === '89504e470d0a1a0a') { + return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) }; + } + return { width: 0, height: 0 }; +} + +/** 生成一个纯 JS 占位 PNG(无需外部依赖),作为兜底 */ +async function writePlaceholder(dest) { + const w = 400, h = 400; + if (render.canvasLib) { + try { + const canvas = render.canvasLib.createCanvas(w, h); + const ctx = canvas.getContext('2d'); + ctx.fillStyle = '#1e1e22'; + ctx.fillRect(0, 0, w, h); + await render.drawSpineBadge(ctx, w, h); + fs.writeFileSync(dest, canvas.toBuffer('image/png')); + return; + } catch (e) { /* fall through to pure JS encoder */ } + } + // 深色底 + const pixels = Buffer.alloc(w * h * 4); + for (let y = 0; y < h; y++) { + for (let x = 0; x < w; x++) { + const i = (y * w + x) * 4; + pixels[i] = 30; pixels[i + 1] = 30; pixels[i + 2] = 34; pixels[i + 3] = 255; + } + } + // 简单的斜线纹理,让占位图不单调 + for (let i = 0; i < w + h; i += 8) { + for (let k = 0; k < 3; k++) { + const x = Math.min(w - 1, i - k); + const y = Math.min(h - 1, k); + const idx = (y * w + x) * 4; + pixels[idx] = 60; pixels[idx + 1] = 62; pixels[idx + 2] = 68; + } + } + fs.writeFileSync(dest, encodePng(w, h, pixels)); +} + +/** 最小 PNG 编码器(纯 JS,使用 zlib deflate) */ +function encodePng(width, height, rgba) { + const sig = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]); + const ihdr = Buffer.alloc(13); + ihdr.writeUInt32BE(width, 0); + ihdr.writeUInt32BE(height, 4); + ihdr[8] = 8; // bit depth + ihdr[9] = 6; // color type RGBA + ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0; + const ihdrChunk = chunk('IHDR', ihdr); + + const raw = Buffer.alloc((width * 4 + 1) * height); + for (let y = 0; y < height; y++) { + raw[y * (width * 4 + 1)] = 0; // filter type 0 + rgba.copy(raw, y * (width * 4 + 1) + 1, y * width * 4, (y + 1) * width * 4); + } + const idat = zlib.deflateSync(raw); + const idatChunk = chunk('IDAT', idat); + const iend = chunk('IEND', Buffer.alloc(0)); + return Buffer.concat([sig, ihdrChunk, idatChunk, iend]); +} + +function chunk(type, data) { + const len = Buffer.alloc(4); + len.writeUInt32BE(data.length, 0); + const typeBuf = Buffer.from(type, 'ascii'); + const crcBuf = Buffer.alloc(4); + crcBuf.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])), 0); + return Buffer.concat([len, typeBuf, data, crcBuf]); +} + +function crc32(buf) { + let c, crc = 0xFFFFFFFF; + for (let i = 0; i < buf.length; i++) { + c = (crc ^ buf[i]) & 0xFF; + for (let k = 0; k < 8; k++) c = c & 1 ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1); + crc = (crc >>> 8) ^ c; + } + return (crc ^ 0xFFFFFFFF) >>> 0; +} diff --git a/release/MAC版本/viewer/spine.html b/release/MAC版本/viewer/spine.html new file mode 100644 index 0000000..f9a58a1 --- /dev/null +++ b/release/MAC版本/viewer/spine.html @@ -0,0 +1,1242 @@ + + + + + + Spine 预览 + + + +
+
+ + + + + + +
+ + + +
+
+ +
+ +
+
+ +
+
+
+
+ 时长 -- + 蓝色短线:关键帧 +
+
+
+ +
+
+ 0.00 / 0.00 秒 · 0 / 0 帧 +
+
+ + + +