From d3d91c25395b9025bad1bc9ba5634c478e19f74d Mon Sep 17 00:00:00 2001 From: Abin Date: Wed, 15 Apr 2026 13:04:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0spine=E5=8A=A8=E7=94=BB?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=99=A8=E5=92=8Cau3=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E8=BD=AC=E6=8D=A2=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spine插件/Spine_动画播放器_2.0/icon.png | Bin 0 -> 12629 bytes Spine插件/Spine_动画播放器_2.0/index.html | 1491 ++ Spine插件/Spine_动画播放器_2.0/logic_3.8.js | 283 + Spine插件/Spine_动画播放器_2.0/logic_4.1.js | 286 + Spine插件/Spine_动画播放器_2.0/logic_4.2.js | 410 + .../Spine_动画播放器_2.0/spine-webgl-3.8.js | 10839 ++++++++++++ .../Spine_动画播放器_2.0/spine-webgl-4.2.js | 14152 ++++++++++++++++ Spine插件/Spine_动画播放器_2.0/spine-webgl.js | 11880 +++++++++++++ .../Spine_动画播放器_2.0/viewer_3.8.html | 302 + .../Spine_动画播放器_2.0/viewer_4.1.html | 302 + .../Spine_动画播放器_2.0/viewer_4.2.html | 422 + Spine插件/Spine_动画播放器_2.0/使用说明.txt | 71 + 压缩包/au3脚本/视频转码.au3 | 241 + 压缩包/au3脚本/视频转码.exe | Bin 0 -> 1038336 bytes 14 files changed, 40679 insertions(+) create mode 100644 Spine插件/Spine_动画播放器_2.0/icon.png create mode 100644 Spine插件/Spine_动画播放器_2.0/index.html create mode 100644 Spine插件/Spine_动画播放器_2.0/logic_3.8.js create mode 100644 Spine插件/Spine_动画播放器_2.0/logic_4.1.js create mode 100644 Spine插件/Spine_动画播放器_2.0/logic_4.2.js create mode 100644 Spine插件/Spine_动画播放器_2.0/spine-webgl-3.8.js create mode 100644 Spine插件/Spine_动画播放器_2.0/spine-webgl-4.2.js create mode 100644 Spine插件/Spine_动画播放器_2.0/spine-webgl.js create mode 100644 Spine插件/Spine_动画播放器_2.0/viewer_3.8.html create mode 100644 Spine插件/Spine_动画播放器_2.0/viewer_4.1.html create mode 100644 Spine插件/Spine_动画播放器_2.0/viewer_4.2.html create mode 100644 Spine插件/Spine_动画播放器_2.0/使用说明.txt create mode 100644 压缩包/au3脚本/视频转码.au3 create mode 100644 压缩包/au3脚本/视频转码.exe diff --git a/Spine插件/Spine_动画播放器_2.0/icon.png b/Spine插件/Spine_动画播放器_2.0/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ca03f3a59dfc3826c6f48c2c28a3254e22730371 GIT binary patch literal 12629 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 + + + + Spine 万能查看器 (3.8 / 4.1 / 4.2) + + + + +
+ + Logo + + +

播放器

+

Universal Spine Viewer

+ +
+ + +
+ +
+ +
等待文件...
+ +
+ + + + +
+ + +
+ + + + +
+ +
+ +
+ + +
+ +
+ + +
+ + +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+ + +
+ +
+ +
+
+
+
+
+ +
+
+ +
+ + +
+ +
+ +
+
+
+
+
+ +
+
+ +
+ + +
+
+ + +
+ +
+ + + + +
+ + +
+ +
+ +
+ + +
+
+ +
+

正在导出序列帧...

+
+

0 / 0

+
+ +
+
+ + +
+ + 0.00 / 0.00 +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+ X + Y +
+
+ +
Waiting...
+ + + + diff --git a/Spine插件/Spine_动画播放器_2.0/logic_3.8.js b/Spine插件/Spine_动画播放器_2.0/logic_3.8.js new file mode 100644 index 0000000..16fdace --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/logic_3.8.js @@ -0,0 +1,283 @@ +// ========================================== +// Spine 3.8 渲染逻辑 (Timeline + DebugDraw) +// ========================================== + +var canvas, gl, shader, batcher, mvp, skeletonRenderer; +var skeleton, animationState; +var lastTime = Date.now(); +var camX=0, camY=0, camZoom=1.0; +// var rendererRequestId = 0; // 移除局部变量 + +function startSpine38(canvasElement, files) { + // 强制停止之前的循环 (双重保险,防止 index.html 没有清理干净) + if(window.viewerConfig.animRequestId) cancelAnimationFrame(window.viewerConfig.animRequestId); + + canvas = canvasElement; + // 关键修改:开启 alpha 通道,并设置 premultipliedAlpha: false + // 这告诉浏览器:Canvas 的内容是 Straight Alpha 的(未预乘)。 + // 即使我们画的是 PMA 数据,如果浏览器认为它是 PMA 并在合成时不再处理,就会导致透明边缘黑边。 + // 这里设为 false,是为了让浏览器在合成到网页背景时,帮我们处理好边缘混合。 + gl = canvas.getContext("webgl", { alpha: true, preserveDrawingBuffer: true, premultipliedAlpha: false }); + + // 如果 Context 丢失 (因为 Canvas 被移除),直接返回 + if(!gl) return; + + // === 关键:全局禁用 WebGL 自动预乘 === + // 我们的纹理已经是 PMA 的了,所以不能让 WebGL 再乘一次。 + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + + // 移除之前的 gl.blendFunc Hack,回归标准流程 + + shader = spine.webgl.Shader.newTwoColoredTextured(gl); + batcher = new spine.webgl.PolygonBatcher(gl); + mvp = new spine.webgl.Matrix4(); + skeletonRenderer = new spine.webgl.SkeletonRenderer(gl); + + // 恢复 PMA 模式 (Normal 混合无黑边) + skeletonRenderer.premultipliedAlpha = true; + addPmaToggle38(); + loadFiles38(files); +} + +function addPmaToggle38() { + const chk = document.getElementById('chk-pma'); + if (chk) { + // 恢复默认勾选 + chk.checked = true; + window.viewerConfig.pmaEnabled = true; + + chk.onchange = (e) => { + window.viewerConfig.pmaEnabled = e.target.checked; + }; + } +} + +async function loadFiles38(files) { + let map = { atlas: null, png: null, main: null, type: null }; + for(let f of files) { + let name = f.name.toLowerCase(); + if(name.endsWith('.atlas') || name.endsWith('.atlas.txt')) map.atlas = f; + else if(name.endsWith('.png') || name.endsWith('.jpg')) map.png = f; + else if(name.endsWith('.skel') || name.endsWith('.skel.bytes')) { map.main = f; map.type = 'binary'; } + else if(name.endsWith('.json') || name.endsWith('.json.txt')) { map.main = f; map.type = 'json'; } + } + + try { + const atlasText = await readFileAsText(map.atlas); + const imgUrl = await readFileAsDataURL(map.png); + + const img = new Image(); + img.onload = async () => { + // 确保不预乘 (防止黑边) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + + const texture = new spine.webgl.GLTexture(gl, img); + const spineAtlas = new spine.TextureAtlas(atlasText, (path) => texture); + const atlasLoader = new spine.AtlasAttachmentLoader(spineAtlas); + + let skeletonData; + if(map.type === 'binary') { + const buffer = await readFileAsArrayBuffer(map.main); + const skeletonBinary = new spine.SkeletonBinary(atlasLoader); + skeletonBinary.scale = 1.0; + skeletonData = skeletonBinary.readSkeletonData(new Uint8Array(buffer)); + } else { + const text = await readFileAsText(map.main); + const skeletonJson = new spine.SkeletonJson(atlasLoader); + skeletonJson.scale = 1.0; + skeletonData = skeletonJson.readSkeletonData(JSON.parse(text)); + } + + setupSkeleton38(skeletonData); + + document.getElementById('ui').style.display = 'block'; + document.getElementById('controls').style.display = 'flex'; + document.getElementById('version-label').innerText = "Spine 3.8 (Binary/JSON)"; + document.getElementById('version-label').style.color = "#ff0055"; + + if(window.viewerConfig.animRequestId) cancelAnimationFrame(window.viewerConfig.animRequestId); + render38(); + }; + img.src = imgUrl; + + } catch(e) { + alert("3.8 加载错误: " + e); + console.error(e); + } +} + +function setupSkeleton38(skeletonData) { + skeleton = new spine.Skeleton(skeletonData); + skeleton.setToSetupPose(); + skeleton.updateWorldTransform(); + skeleton.x = 0; skeleton.y = 0; + + // 暴露实例供导出使用 + window.spineInstance = { skeleton: skeleton, state: animationState, gl: gl }; + + var stateData = new spine.AnimationStateData(skeleton.data); + animationState = new spine.AnimationState(stateData); + + const animSelect = document.getElementById('anim-select'); + animSelect.innerHTML = ""; + skeleton.data.animations.forEach(a => { + const opt = document.createElement('option'); + opt.value = a.name; opt.text = a.name; animSelect.appendChild(opt); + }); + if(skeleton.data.animations.length > 0) animationState.setAnimation(0, skeleton.data.animations[0].name, true); + + const skinSelect = document.getElementById('skin-select'); + skinSelect.innerHTML = ""; + skeleton.data.skins.forEach(s => { + const opt = document.createElement('option'); + opt.value = s.name; opt.text = s.name; skinSelect.appendChild(opt); + }); + if(skeleton.data.defaultSkin) skinSelect.value = skeleton.data.defaultSkin.name; + + animSelect.onchange = () => animationState.setAnimation(0, animSelect.value, true); + skinSelect.onchange = () => { skeleton.setSkinByName(skinSelect.value); skeleton.setSlotsToSetupPose(); }; + + bindControls38(); + updateControls38(); +} + +function render38() { + // 将 requestId 存储到全局配置中,以便其他地方可以取消 + window.viewerConfig.animRequestId = requestAnimationFrame(render38); + + // 检查 canvas 是否还存在于 DOM 中 (防止僵尸循环) + if(!canvas.parentElement) { + cancelAnimationFrame(window.viewerConfig.animRequestId); + return; + } + + let now = Date.now(); + const targetFps = window.viewerConfig.targetFps || 30; + const interval = 1000 / targetFps; + const elapsed = now - lastTime; + + if (elapsed < interval) return; + + lastTime = now - (elapsed % interval); + let delta = elapsed / 1000; + + // 应用倍速 + delta *= (window.viewerConfig.speed || 1.0); + + // === 导出模式判断 === + const isExporting = window.viewerConfig.isExporting; + + if (!isExporting) { + // 只有非导出模式下才跟随窗口大小 + if(canvas.width !== window.innerWidth) canvas.width = window.innerWidth; + if(canvas.height !== window.innerHeight) canvas.height = window.innerHeight; + } + + let w = canvas.width; + let h = canvas.height; + gl.viewport(0, 0, w, h); + + if (isExporting) { + gl.clearColor(0, 0, 0, 0); // 强制全透明 + } else { + const bg = window.viewerConfig ? window.viewerConfig.bgColor : [0.2, 0.2, 0.2, 1]; + gl.clearColor(bg[0], bg[1], bg[2], bg[3]); + } + gl.clear(gl.COLOR_BUFFER_BIT); + + // === 关键修复:同步 PMA 设置 === + // 确保每一帧都从全局配置读取 PMA 状态,并应用到 skeletonRenderer + if (window.viewerConfig) { + skeletonRenderer.premultipliedAlpha = window.viewerConfig.pmaEnabled; + } + + if (skeleton && animationState) { + const ctrl = window.animControl; + let track = animationState.tracks[0]; + + if (track) { + if (ctrl) ctrl.updateUI(track.trackTime, track.animation.duration); + if (ctrl && ctrl.isScrubbing && ctrl.targetTime >= 0) { + track.trackTime = ctrl.targetTime; + } + else if (ctrl && !ctrl.isPlaying) { + animationState.update(0); + } + else { + animationState.update(delta); + } + } else { + animationState.update(delta); + } + + animationState.apply(skeleton); + skeleton.updateWorldTransform(); + + shader.bind(); + mvp.ortho2d(camX - w/2/camZoom, camY - h/2/camZoom, w/camZoom, h/camZoom); + shader.setUniform4x4f(spine.webgl.Shader.MVP_MATRIX, mvp.values); + shader.setUniformi(spine.webgl.Shader.SAMPLER, 0); + + // 关键修复:不要手动调用 gl.blendFunc,因为 skeletonRenderer.draw 会根据 Slot 模式自己设置 + // 我们只需要确保 skeletonRenderer.premultipliedAlpha 是对的 + if (window.viewerConfig) { + skeletonRenderer.premultipliedAlpha = window.viewerConfig.pmaEnabled; + } + + batcher.begin(shader); + skeletonRenderer.draw(batcher, skeleton); + batcher.end(); + shader.unbind(); + + // === 绘制骨骼调试线 (导出时不绘制) === + if(!isExporting) { + if(window.debugRenderer && window.viewerConfig.showBones) { + window.debugRenderer.drawBones(skeleton, camX, camY, camZoom, h); + } else if(window.debugRenderer) { + window.debugRenderer.drawBones(null, 0,0,1,0); // 清空 + } + } + } +} + +function updateControls38() { + document.getElementById('posX').value = skeleton.x; + document.getElementById('posY').value = skeleton.y; +} + +function bindControls38() { + const inputX = document.getElementById('posX'); + const inputY = document.getElementById('posY'); + inputX.oninput = () => { if(skeleton) skeleton.x = parseFloat(inputX.value); }; + inputY.oninput = () => { if(skeleton) skeleton.y = parseFloat(inputY.value); }; + + window.resetView = function() { + skeleton.x = 0; skeleton.y = 0; + camX=0; camY=0; camZoom=1.0; + updateControls38(); + }; + + let isDragging=false, startX, startY, isRightDrag=false; + canvas.oncontextmenu = e => e.preventDefault(); + canvas.onmousedown = e => { + if(e.button === 2) isRightDrag = true; else isDragging = true; + startX = e.clientX; startY = e.clientY; + }; + window.onmouseup = () => { isDragging=false; isRightDrag=false; }; + window.onmousemove = e => { + if(isDragging) { + camX -= (e.clientX - startX) / camZoom; + camY += (e.clientY - startY) / camZoom; + startX = e.clientX; startY = e.clientY; + } else if(isRightDrag) { + let dy = e.clientY - startY; + let newZoom = camZoom * (1 + dy * 0.01); + if(newZoom > 0.1 && newZoom < 10) camZoom = newZoom; + startY = e.clientY; + } + }; + canvas.onwheel = e => { + let newZoom = camZoom * (e.deltaY > 0 ? 0.9 : 1.1); + if(newZoom > 0.1 && newZoom < 10) camZoom = newZoom; + }; +} diff --git a/Spine插件/Spine_动画播放器_2.0/logic_4.1.js b/Spine插件/Spine_动画播放器_2.0/logic_4.1.js new file mode 100644 index 0000000..31ad2b8 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/logic_4.1.js @@ -0,0 +1,286 @@ +// ========================================== +// Spine 4.1 渲染逻辑 (Timeline + DebugDraw) +// ========================================== + +var canvas, gl, renderer, assetManager, skeleton, animationState; +var lastTime = Date.now(); +var rendererRequestId = 0; + +function startSpine41(canvasElement, files) { + if(window.viewerConfig.animRequestId) cancelAnimationFrame(window.viewerConfig.animRequestId); + + canvas = canvasElement; + // 关键修复:添加 premultipliedAlpha: false,解决半透明黑边问题 + gl = canvas.getContext("webgl", { alpha: true, preserveDrawingBuffer: true, premultipliedAlpha: false }); + + if(!gl) return; + + // 确保 WebGL 不自动预乘 (因为 PMA 图片本身已经是预乘过的) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + + renderer = new spine.SceneRenderer(canvas, gl); + assetManager = new spine.AssetManager(gl); + + renderer.premultipliedAlpha = true; + addPmaToggle41(); + loadFiles41(files); +} + +function addPmaToggle41() { + // 适配新版 UI:直接复用 index.html 的 chk-pma,不再重复创建 + const chk = document.getElementById('chk-pma'); + if (chk) { + // 绑定事件 + chk.onchange = (e) => { + window.viewerConfig.pmaEnabled = e.target.checked; + if(renderer) { + renderer.premultipliedAlpha = e.target.checked; + } + }; + // 初始化 + window.viewerConfig.pmaEnabled = chk.checked; + if(renderer) renderer.premultipliedAlpha = chk.checked; + } +} + +async function loadFiles41(files) { + let map = { atlas: null, png: null, main: null, type: null }; + for(let f of files) { + let name = f.name.toLowerCase(); + if(name.endsWith('.atlas') || name.endsWith('.atlas.txt')) map.atlas = f; + else if(name.endsWith('.png') || name.endsWith('.jpg')) map.png = f; + else if(name.endsWith('.skel') || name.endsWith('.skel.bytes')) { map.main = f; map.type = 'binary'; } + else if(name.endsWith('.json') || name.endsWith('.json.txt')) { map.main = f; map.type = 'json'; } + } + + try { + const atlasText = await readFileAsText(map.atlas); + const imgUrl = await readFileAsDataURL(map.png); + + const img = new Image(); + img.onload = async () => { + const texture = new spine.GLTexture(gl, img); + const spineAtlas = new spine.TextureAtlas(atlasText, (path) => texture); + + for (let i = 0; i < spineAtlas.pages.length; i++) { + spineAtlas.pages[i].texture = texture; + spineAtlas.pages[i].width = img.width; + spineAtlas.pages[i].height = img.height; + } + + const atlasLoader = new spine.AtlasAttachmentLoader(spineAtlas); + let skeletonData; + + if(map.type === 'binary') { + const buffer = await readFileAsArrayBuffer(map.main); + const skeletonBinary = new spine.SkeletonBinary(atlasLoader); + skeletonBinary.scale = 1.0; + skeletonData = skeletonBinary.readSkeletonData(new Uint8Array(buffer)); + } else { + const text = await readFileAsText(map.main); + const skeletonJson = new spine.SkeletonJson(atlasLoader); + skeletonJson.scale = 1.0; + const jsonObj = JSON.parse(text); + if(jsonObj.skeleton) jsonObj.skeleton.images = ""; + skeletonData = skeletonJson.readSkeletonData(jsonObj); + } + + setupSkeleton41(skeletonData); + + document.getElementById('ui').style.display = 'block'; + document.getElementById('controls').style.display = 'flex'; + document.getElementById('version-label').innerText = "Spine 4.1 (Binary/JSON)"; + document.getElementById('version-label').style.color = "#00e5ff"; + + if(rendererRequestId) cancelAnimationFrame(rendererRequestId); + requestAnimationFrame(render41); + }; + img.src = imgUrl; + + } catch(e) { + alert("4.1 加载错误: " + e); + console.error(e); + } +} + +function setupSkeleton41(skeletonData) { + skeleton = new spine.Skeleton(skeletonData); + skeleton.setToSetupPose(); + skeleton.updateWorldTransform(); + skeleton.x = 0; skeleton.y = -500; + + // 暴露实例供导出使用 + window.spineInstance = { skeleton: skeleton, state: animationState, gl: gl, renderer: renderer }; + + renderer.camera.position.x = 0; + renderer.camera.position.y = 0; + renderer.camera.zoom = 1.0; + + var stateData = new spine.AnimationStateData(skeleton.data); + animationState = new spine.AnimationState(stateData); + + const animSelect = document.getElementById('anim-select'); + animSelect.innerHTML = ""; + skeleton.data.animations.forEach(a => { + const opt = document.createElement('option'); + opt.value = a.name; opt.text = a.name; animSelect.appendChild(opt); + }); + if(skeleton.data.animations.length > 0) animationState.setAnimation(0, skeleton.data.animations[0].name, true); + + const skinSelect = document.getElementById('skin-select'); + skinSelect.innerHTML = ""; + skeleton.data.skins.forEach(s => { + const opt = document.createElement('option'); + opt.value = s.name; opt.text = s.name; skinSelect.appendChild(opt); + }); + if(skeleton.data.defaultSkin) skinSelect.value = skeleton.data.defaultSkin.name; + + animSelect.onchange = () => animationState.setAnimation(0, animSelect.value, true); + skinSelect.onchange = () => { skeleton.setSkinByName(skinSelect.value); skeleton.setSlotsToSetupPose(); }; + + bindControls41(); + updateControls41(); +} + +function render41() { + // 将 requestId 存储到全局配置中 + window.viewerConfig.animRequestId = requestAnimationFrame(render41); + + // 检查 canvas 是否还存在于 DOM 中 + if(!canvas.parentElement) { + cancelAnimationFrame(window.viewerConfig.animRequestId); + return; + } + + let now = Date.now(); + const targetFps = window.viewerConfig.targetFps || 30; + const interval = 1000 / targetFps; + const elapsed = now - lastTime; + + if (elapsed < interval) return; + + lastTime = now - (elapsed % interval); + let delta = elapsed / 1000; + + // 应用倍速 + delta *= (window.viewerConfig.speed || 1.0); + + // === 导出模式判断 === + const isExporting = window.viewerConfig.isExporting; + + if (!isExporting) { + let w = window.innerWidth; + let h = window.innerHeight; + if(canvas.width !== w || canvas.height !== h) { + canvas.width = w; + canvas.height = h; + } + } + + let w = canvas.width; + let h = canvas.height; + gl.viewport(0, 0, w, h); + + if(renderer.camera.viewportWidth !== w || renderer.camera.viewportHeight !== h) { + renderer.camera.viewportWidth = w; + renderer.camera.viewportHeight = h; + renderer.camera.update(); + } + + if (isExporting) { + gl.clearColor(0, 0, 0, 0); // 强制全透明 + } else { + const bg = window.viewerConfig ? window.viewerConfig.bgColor : [0.2, 0.2, 0.2, 1]; + gl.clearColor(bg[0], bg[1], bg[2], bg[3]); + } + gl.clear(gl.COLOR_BUFFER_BIT); + + // === 关键修复:同步 PMA 设置 === + // 确保每一帧都从全局配置读取 PMA 状态,并应用到 renderer + if (renderer && window.viewerConfig) { + renderer.premultipliedAlpha = window.viewerConfig.pmaEnabled; + } + + if (skeleton && animationState) { + const ctrl = window.animControl; + let track = animationState.getCurrent(0); + + if (track) { + if (ctrl) ctrl.updateUI(track.trackTime, track.animation.duration); + if (ctrl && ctrl.isScrubbing && ctrl.targetTime >= 0) { + track.trackTime = ctrl.targetTime; + } + else if (ctrl && !ctrl.isPlaying) { + animationState.update(0); + } + else { + animationState.update(delta); + } + } else { + animationState.update(delta); + } + + animationState.apply(skeleton); + skeleton.updateWorldTransform(); + renderer.begin(); + renderer.drawSkeleton(skeleton, true); + renderer.end(); + + // === 绘制骨骼调试线 (导出时不绘制) === + if(!isExporting) { + if(window.debugRenderer && window.viewerConfig.showBones) { + window.debugRenderer.drawBones( + skeleton, + renderer.camera.position.x, + renderer.camera.position.y, + renderer.camera.zoom, + h + ); + } else if(window.debugRenderer) { + window.debugRenderer.drawBones(null, 0,0,1,0); + } + } + } +} + +function updateControls41() { + document.getElementById('posX').value = skeleton.x; + document.getElementById('posY').value = skeleton.y; +} + +function bindControls41() { + const inputX = document.getElementById('posX'); + const inputY = document.getElementById('posY'); + inputX.oninput = () => { if(skeleton) skeleton.x = parseFloat(inputX.value); }; + inputY.oninput = () => { if(skeleton) skeleton.y = parseFloat(inputY.value); }; + + window.resetView = function() { + skeleton.x = 0; skeleton.y = -500; + renderer.camera.position.x = 0; renderer.camera.position.y = 0; renderer.camera.zoom = 1.0; + updateControls41(); + }; + + let isDragging=false, startX, startY, isRightDrag=false; + canvas.oncontextmenu = e => e.preventDefault(); + canvas.onmousedown = e => { + if(e.button === 2) isRightDrag = true; else isDragging = true; + startX = e.clientX; startY = e.clientY; + }; + window.onmouseup = () => { isDragging=false; isRightDrag=false; }; + window.onmousemove = e => { + if(isDragging) { + renderer.camera.position.x -= (e.clientX - startX) * renderer.camera.zoom; + renderer.camera.position.y += (e.clientY - startY) * renderer.camera.zoom; + startX = e.clientX; startY = e.clientY; + } else if(isRightDrag) { + let dy = e.clientY - startY; + let newZoom = renderer.camera.zoom * (1 + dy * 0.01); + if(newZoom > 0.1 && newZoom < 10) renderer.camera.zoom = newZoom; + startY = e.clientY; + } + }; + canvas.onwheel = e => { + let newZoom = renderer.camera.zoom * (e.deltaY > 0 ? 1.1 : 0.9); + if(newZoom > 0.1 && newZoom < 10) renderer.camera.zoom = newZoom; + }; +} diff --git a/Spine插件/Spine_动画播放器_2.0/logic_4.2.js b/Spine插件/Spine_动画播放器_2.0/logic_4.2.js new file mode 100644 index 0000000..66e37e9 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/logic_4.2.js @@ -0,0 +1,410 @@ +// Spine 4.2 逻辑适配器 (基于 V30 + 全局配置 + Timeline + DebugDraw) +window.startSpine42 = async function(canvas, files) { + console.log("启动 Spine 4.2 引擎..."); + + // ============================================================= + // 动态增强 UI + // ============================================================= + const uiPanel = document.getElementById('ui'); + + // 适配新版 UI:绑定现有的 PMA checkbox + const chkPma = document.getElementById('chk-pma'); + if (chkPma) { + chkPma.onchange = (e) => { + // 4.2 可能需要特定的处理,或者只是重绘 + // 这里假设 render loop 会读取 global pma setting + window.viewerConfig.pmaEnabled = e.target.checked; + }; + } + + // 物理重置按钮保留,但样式微调 + if (!document.getElementById('btn-reset-phy')) { + const btn = document.createElement('button'); + btn.id = 'btn-reset-phy'; + btn.innerText = "💥 重置物理"; + btn.className = 'btn-export'; // 复用导出按钮的样式 + btn.style.marginTop = '15px'; + btn.style.background = '#880000'; // 特殊颜色 + btn.onclick = () => resetPhysics(); + uiPanel.appendChild(btn); + } + + // ============================================================= + // 核心变量 + // ============================================================= + const ui = { + log: (msg, type) => { + console.log(msg); + const box = document.getElementById('log'); + if(box) box.innerText = msg; + }, + updateSliders: () => { + const sx = document.getElementById('posX'); + const sy = document.getElementById('posY'); + if(sx) sx.value = cam.x; + if(sy) sy.value = cam.y; + } + }; + + const Mat4 = { + create: () => new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]), + ortho: (out, l, r, b, t, n, f) => { + const lr = 1/(l-r), bt = 1/(b-t), nf = 1/(n-f); + out[0]=-2*lr; out[5]=-2*bt; out[10]=2*nf; out[12]=(l+r)*lr; out[13]=(t+b)*bt; out[14]=(f+n)*nf; out[15]=1; + } + }; + + let gl, shader, batcher, renderer; + let skeleton, state, mvp = Mat4.create(); + let lastTime = Date.now(); + let cam = {x:0, y:0, zoom:1.0}; + window.cam42 = cam; // 暴露给导出脚本使用 + let globalTexture = null; + const Physics = { None: 0, Update: 1, Reset: 2 }; + + // ============================================================= + // 初始化 WebGL + // ============================================================= + try { + // 关键修复:添加 premultipliedAlpha: false,解决半透明黑边问题 + gl = canvas.getContext('webgl', { alpha: true, preserveDrawingBuffer: true, premultipliedAlpha: false }); + if(!gl) throw "WebGL 不可用"; + + // 确保 WebGL 不自动预乘 (因为 PMA 图片本身已经是预乘过的) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + + shader = spine.Shader.newTwoColoredTextured(gl); + batcher = new spine.PolygonBatcher(gl, true); + renderer = new spine.SkeletonRenderer(gl); + renderer.twoColor = true; + renderer.premultipliedAlpha = true; + + bindInput(); + + // 开始处理文件 + handleFiles(files); + + // 启动循环 + requestAnimationFrame(loop); + + } catch(e) { ui.log("初始化失败: " + e, 'err'); } + + // ============================================================= + // 输入绑定 + // ============================================================= + function bindInput() { + // 鼠标/滚轮控制 + canvas.onwheel = e => { + cam.zoom *= (e.deltaY>0 ? 0.9 : 1.1); + if(cam.zoom < 0.1) cam.zoom = 0.1; + if(cam.zoom > 10) cam.zoom = 10; + }; + + let drag=false, lx, ly, isRight=false; + + canvas.oncontextmenu = e => e.preventDefault(); + canvas.onmousedown = e => { + drag=true; + isRight = (e.button === 2); + lx=e.clientX; ly=e.clientY; + }; + window.onmouseup = () => drag=false; + + window.onmousemove = e => { + if(drag) { + let dx = e.clientX - lx; + let dy = e.clientY - ly; + + if(isRight) { + let newZoom = cam.zoom * (1 + dy * 0.005); + if(newZoom > 0.1 && newZoom < 10) cam.zoom = newZoom; + } else { + cam.x -= dx / cam.zoom; + cam.y += dy / cam.zoom; + + // 物理惯性 + if (skeleton) { + skeleton.x += dx / cam.zoom; + skeleton.y -= dy / cam.zoom; + } + ui.updateSliders(); + } + lx = e.clientX; ly = e.clientY; + } + }; + + const sx = document.getElementById('posX'); + const sy = document.getElementById('posY'); + if(sx) sx.oninput = () => cam.x = parseFloat(sx.value); + if(sy) sy.oninput = () => cam.y = parseFloat(sy.value); + + // 绑定全局归位函数 + window.resetView = function() { + if(skeleton) { + // 4.2 需要同时重置摄像机和骨骼位置(如果有物理惯性) + cam.x = 0; + cam.y = -200; // 4.2 默认稍微向下偏移一点 + cam.zoom = 1.0; + + // 重置滑块 + if(sx) sx.value = 0; + if(sy) sy.value = -200; + + ui.log("视图已重置"); + } + }; + } + + function resetPhysics() { + if(skeleton && spine.Physics) { + skeleton.updateWorldTransform(spine.Physics.reset); + ui.log("物理已重置"); + } + } + + // ============================================================= + // 文件处理 + // ============================================================= + async function handleFiles(fileList) { + let map = {}; + for(let f of fileList) { + let n = f.name.toLowerCase(); + if(n.includes('.atlas')) map.atlas = f; + else if(n.includes('.png') || n.includes('.jpg') || n.includes('.webp')) map.png = f; + else if(n.includes('.skel') || n.includes('.json')) map.main = f; + } + + if(!map.atlas || !map.png || !map.main) { + ui.log("文件缺失: 需要 .json/.skel + .atlas + .png", 'err'); + return; + } + + try { + const imgBlob = URL.createObjectURL(map.png); + const img = new Image(); + img.onload = () => processSpine(map, img); + img.src = imgBlob; + } catch(e) { ui.log(e, 'err'); } + } + + async function processSpine(map, img) { + try { + ui.log("正在加载 (Spine 4.2)..."); + const atlasText = await readFile(map.atlas, 'text'); + + globalTexture = new spine.GLTexture(gl, img, false); + globalTexture.setFilters(gl.LINEAR, gl.LINEAR); + globalTexture.setWraps(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE); + + const atlas = new spine.TextureAtlas(atlasText, path => globalTexture); + // 强制修正 Atlas 尺寸 + for(let page of atlas.pages) { page.width = img.width; page.height = img.height; } + + const loader = new spine.AtlasAttachmentLoader(atlas); + let skelData; + + if(map.main.name.includes('.skel')) { + ui.log("解析二进制文件..."); + const buffer = await readFile(map.main, 'array'); + skelData = new spine.SkeletonBinary(loader).readSkeletonData(new Uint8Array(buffer)); + } else { + ui.log("解析 JSON 文件..."); + const text = await readFile(map.main, 'text'); + skelData = new spine.SkeletonJson(loader).readSkeletonData(JSON.parse(text)); + } + + ui.log(`版本: ${skelData.version}`); + + skeleton = new spine.Skeleton(skelData); + window.skeleton = skeleton; // 暴露给导出脚本 + + // 自动注入纹理 + let fixCount = 0; + for(let skin of skeleton.data.skins) { + let entries = skin.getAttachments ? skin.getAttachments() : skin.attachments; + for(let entry of entries) { + let att = entry ? entry.attachment : null; + if(att && att.region) { + att.region.texture = globalTexture; + att.region.renderObject = att.region; + fixCount++; + } + } + } + + skeleton.setToSetupPose(); + if(spine.Physics) skeleton.updateWorldTransform(spine.Physics.reset); + + state = new spine.AnimationState(new spine.AnimationStateData(skelData)); + + setupUI(skelData); + + // 预热两帧 + state.update(0); state.apply(skeleton); skeleton.updateWorldTransform(spine.Physics.update); + state.update(0); state.apply(skeleton); skeleton.updateWorldTransform(spine.Physics.update); + + // 自动对焦 + const offset = new spine.Vector2(), size = new spine.Vector2(); + skeleton.getBounds(offset, size, []); + if(size.x > 0) { + cam.x = offset.x + size.x/2; + cam.y = offset.y + size.y/2; + cam.zoom = Math.min(canvas.width/size.x, canvas.height/size.y) * 0.8; + } else { + cam.x = 0; cam.y = -200; + } + ui.updateSliders(); + + // 显示UI + document.getElementById('ui').style.display = 'block'; + document.getElementById('controls').style.display = 'flex'; + + } catch(e) { ui.log(e.message, 'err'); } + } + + function setupUI(data) { + const animSelect = document.getElementById('anim-select'); + const skinSelect = document.getElementById('skin-select'); + if(!animSelect || !skinSelect) return; + + animSelect.innerHTML = ""; + skinSelect.innerHTML = ""; + + data.animations.forEach(a => { + const opt = document.createElement('option'); + opt.value = a.name; opt.text = a.name; animSelect.appendChild(opt); + }); + + if(data.animations.length > 0) { + state.setAnimation(0, data.animations[0].name, true); + } + + data.skins.forEach(s => { + const opt = document.createElement('option'); + opt.value = s.name; opt.text = s.name; skinSelect.appendChild(opt); + }); + if(data.defaultSkin) skinSelect.value = data.defaultSkin.name; + + animSelect.onchange = () => state.setAnimation(0, animSelect.value, true); + skinSelect.onchange = () => { + skeleton.setSkinByName(skinSelect.value); + skeleton.setSlotsToSetupPose(); + skeleton.setToSetupPose(); + if(spine.Physics) skeleton.updateWorldTransform(spine.Physics.reset); + }; + } + + function readFile(f, type) { + return new Promise(r => { + const fr = new FileReader(); + fr.onload = () => r(fr.result); + if(type==='text') fr.readAsText(f); else fr.readAsArrayBuffer(f); + }); + } + + // ============================================================= + // 渲染循环 + // ============================================================= + function loop() { + requestAnimationFrame(loop); + + const now = Date.now(); + const targetFps = window.viewerConfig.targetFps || 30; + const interval = 1000 / targetFps; + const elapsed = now - lastTime; + + if (elapsed < interval) return; + + lastTime = now - (elapsed % interval); + let dt = elapsed / 1000; + + // 应用倍速 + const speed = window.viewerConfig.speed || 1.0; + dt *= speed; + + // === 导出模式判断 === + const isExporting = window.viewerConfig.isExporting; + + if (!isExporting) { + if(canvas.width !== window.innerWidth) { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } + } + + gl.viewport(0, 0, canvas.width, canvas.height); + + if (isExporting) { + gl.clearColor(0, 0, 0, 0); // 强制全透明 + } else { + const bg = window.viewerConfig ? window.viewerConfig.bgColor : [0.2, 0.2, 0.2, 1]; + gl.clearColor(bg[0], bg[1], bg[2], bg[3]); + } + gl.clear(gl.COLOR_BUFFER_BIT); + + if(!skeleton || !state) return; + + try { + // === 时间轴核心控制 === + const ctrl = window.animControl; + let track = state.getCurrent(0); + + if (track) { + if (ctrl) ctrl.updateUI(track.trackTime, track.animation.duration); + if (ctrl && ctrl.isScrubbing && ctrl.targetTime >= 0) { + track.trackTime = ctrl.targetTime; + } + else if (ctrl && !ctrl.isPlaying) { + if (skeleton.update) skeleton.update(0); + state.update(0); + } + else { + state.update(dt); + } + } else { + state.update(dt); + } + + state.apply(skeleton); + + // 物理更新逻辑 + if(skeleton.update && (!ctrl || (ctrl.isPlaying && !ctrl.isScrubbing))) { + skeleton.update(dt); + } + if(spine.Physics) skeleton.updateWorldTransform(spine.Physics.update); + else skeleton.updateWorldTransform(1); + + if(!Number.isFinite(cam.zoom)) cam.zoom=0.1; + const w = canvas.width, h = canvas.height; + Mat4.ortho(mvp, cam.x - w/cam.zoom/2, cam.x + w/cam.zoom/2, cam.y - h/cam.zoom/2, cam.y + h/cam.zoom/2, -2000, 2000); + + shader.bind(); + shader.setUniform4x4f(spine.Shader.MVP_MATRIX, mvp); + shader.setUniformi(spine.Shader.SAMPLER, 0); + + // 从全局配置读取 PMA + const pma = window.viewerConfig ? window.viewerConfig.pmaEnabled : true; + + gl.enable(gl.BLEND); + gl.blendFunc(pma ? gl.ONE : gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + batcher.begin(shader); + renderer.draw(batcher, skeleton); + batcher.end(); + shader.unbind(); + + // === 绘制骨骼调试线 (导出时不绘制) === + if(!isExporting) { + if(window.debugRenderer && window.viewerConfig.showBones) { + window.debugRenderer.drawBones( + skeleton, + cam.x, + cam.y, + cam.zoom, + h + ); + } else if(window.debugRenderer) { + window.debugRenderer.drawBones(null, 0,0,1,0); + } + } + + } catch(e) { } + } +}; diff --git a/Spine插件/Spine_动画播放器_2.0/spine-webgl-3.8.js b/Spine插件/Spine_动画播放器_2.0/spine-webgl-3.8.js new file mode 100644 index 0000000..c6395ed --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/spine-webgl-3.8.js @@ -0,0 +1,10839 @@ +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 webgl; + (function (webgl) { + var AssetManager = (function (_super) { + __extends(AssetManager, _super); + function AssetManager(context, pathPrefix) { + if (pathPrefix === void 0) { pathPrefix = ""; } + return _super.call(this, function (image) { + return new spine.webgl.GLTexture(context, image); + }, pathPrefix) || this; + } + return AssetManager; + }(spine.AssetManager)); + webgl.AssetManager = AssetManager; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var OrthoCamera = (function () { + function OrthoCamera(viewportWidth, viewportHeight) { + this.position = new webgl.Vector3(0, 0, 0); + this.direction = new webgl.Vector3(0, 0, -1); + this.up = new webgl.Vector3(0, 1, 0); + this.near = 0; + this.far = 100; + this.zoom = 1; + this.viewportWidth = 0; + this.viewportHeight = 0; + this.projectionView = new webgl.Matrix4(); + this.inverseProjectionView = new webgl.Matrix4(); + this.projection = new webgl.Matrix4(); + this.view = new webgl.Matrix4(); + this.tmp = new webgl.Vector3(); + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.update(); + } + OrthoCamera.prototype.update = function () { + var projection = this.projection; + var view = this.view; + var projectionView = this.projectionView; + var inverseProjectionView = this.inverseProjectionView; + var zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight; + projection.ortho(zoom * (-viewportWidth / 2), zoom * (viewportWidth / 2), zoom * (-viewportHeight / 2), zoom * (viewportHeight / 2), this.near, this.far); + view.lookAt(this.position, this.direction, this.up); + projectionView.set(projection.values); + projectionView.multiply(view); + inverseProjectionView.set(projectionView.values).invert(); + }; + OrthoCamera.prototype.screenToWorld = function (screenCoords, screenWidth, screenHeight) { + var x = screenCoords.x, y = screenHeight - screenCoords.y - 1; + var tmp = this.tmp; + tmp.x = (2 * x) / screenWidth - 1; + tmp.y = (2 * y) / screenHeight - 1; + tmp.z = (2 * screenCoords.z) - 1; + tmp.project(this.inverseProjectionView); + screenCoords.set(tmp.x, tmp.y, tmp.z); + return screenCoords; + }; + OrthoCamera.prototype.setViewport = function (viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + }; + return OrthoCamera; + }()); + webgl.OrthoCamera = OrthoCamera; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var GLTexture = (function (_super) { + __extends(GLTexture, _super); + function GLTexture(context, image, useMipMaps) { + if (useMipMaps === void 0) { useMipMaps = false; } + var _this = _super.call(this, image) || this; + _this.texture = null; + _this.boundUnit = 0; + _this.useMipMaps = false; + _this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + _this.useMipMaps = useMipMaps; + _this.restore(); + _this.context.addRestorable(_this); + return _this; + } + GLTexture.prototype.setFilters = function (minFilter, magFilter) { + var gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, GLTexture.validateMagFilter(magFilter)); + }; + GLTexture.validateMagFilter = function (magFilter) { + switch (magFilter) { + case spine.TextureFilter.MipMap: + case spine.TextureFilter.MipMapLinearLinear: + case spine.TextureFilter.MipMapLinearNearest: + case spine.TextureFilter.MipMapNearestLinear: + case spine.TextureFilter.MipMapNearestNearest: + return spine.TextureFilter.Linear; + default: + return magFilter; + } + }; + GLTexture.prototype.setWraps = function (uWrap, vWrap) { + var gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap); + }; + GLTexture.prototype.update = function (useMipMaps) { + var gl = this.context.gl; + if (!this.texture) { + this.texture = this.context.gl.createTexture(); + } + this.bind(); + if (GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : 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); + if (useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + }; + GLTexture.prototype.restore = function () { + this.texture = null; + this.update(this.useMipMaps); + }; + GLTexture.prototype.bind = function (unit) { + if (unit === void 0) { unit = 0; } + var gl = this.context.gl; + this.boundUnit = unit; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + }; + GLTexture.prototype.unbind = function () { + var gl = this.context.gl; + gl.activeTexture(gl.TEXTURE0 + this.boundUnit); + gl.bindTexture(gl.TEXTURE_2D, null); + }; + GLTexture.prototype.dispose = function () { + this.context.removeRestorable(this); + var gl = this.context.gl; + gl.deleteTexture(this.texture); + }; + GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false; + return GLTexture; + }(spine.Texture)); + webgl.GLTexture = GLTexture; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var Input = (function () { + function Input(element) { + this.lastX = 0; + this.lastY = 0; + this.buttonDown = false; + this.currTouch = null; + this.touchesPool = new spine.Pool(function () { + return new spine.webgl.Touch(0, 0, 0); + }); + this.listeners = new Array(); + this.element = element; + this.setupCallbacks(element); + } + Input.prototype.setupCallbacks = function (element) { + var _this = this; + var mouseDown = function (ev) { + if (ev instanceof MouseEvent) { + var rect = element.getBoundingClientRect(); + var x = ev.clientX - rect.left; + var y = ev.clientY - rect.top; + var listeners = _this.listeners; + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].down) + listeners[i].down(x, y); + } + _this.lastX = x; + _this.lastY = y; + _this.buttonDown = true; + document.addEventListener("mousemove", mouseMove); + document.addEventListener("mouseup", mouseUp); + } + }; + var mouseMove = function (ev) { + if (ev instanceof MouseEvent) { + var rect = element.getBoundingClientRect(); + var x = ev.clientX - rect.left; + var y = ev.clientY - rect.top; + var listeners = _this.listeners; + for (var i = 0; i < listeners.length; i++) { + if (_this.buttonDown) { + if (listeners[i].dragged) + listeners[i].dragged(x, y); + } + else { + if (listeners[i].moved) + listeners[i].moved(x, y); + } + } + _this.lastX = x; + _this.lastY = y; + } + }; + var mouseUp = function (ev) { + if (ev instanceof MouseEvent) { + var rect = element.getBoundingClientRect(); + var x = ev.clientX - rect.left; + var y = ev.clientY - rect.top; + var listeners = _this.listeners; + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].up) + listeners[i].up(x, y); + } + _this.lastX = x; + _this.lastY = y; + _this.buttonDown = false; + document.removeEventListener("mousemove", mouseMove); + document.removeEventListener("mouseup", mouseUp); + } + }; + element.addEventListener("mousedown", mouseDown, true); + element.addEventListener("mousemove", mouseMove, true); + element.addEventListener("mouseup", mouseUp, true); + element.addEventListener("touchstart", function (ev) { + if (_this.currTouch != null) + return; + var touches = ev.changedTouches; + for (var i = 0; i < touches.length; i++) { + var touch = touches[i]; + var rect = element.getBoundingClientRect(); + var x = touch.clientX - rect.left; + var y = touch.clientY - rect.top; + _this.currTouch = _this.touchesPool.obtain(); + _this.currTouch.identifier = touch.identifier; + _this.currTouch.x = x; + _this.currTouch.y = y; + break; + } + var listeners = _this.listeners; + for (var i_17 = 0; i_17 < listeners.length; i_17++) { + if (listeners[i_17].down) + listeners[i_17].down(_this.currTouch.x, _this.currTouch.y); + } + _this.lastX = _this.currTouch.x; + _this.lastY = _this.currTouch.y; + _this.buttonDown = true; + ev.preventDefault(); + }, false); + element.addEventListener("touchend", function (ev) { + var touches = ev.changedTouches; + for (var i = 0; i < touches.length; i++) { + var touch = touches[i]; + if (_this.currTouch.identifier === touch.identifier) { + var rect = element.getBoundingClientRect(); + var x = _this.currTouch.x = touch.clientX - rect.left; + var y = _this.currTouch.y = touch.clientY - rect.top; + _this.touchesPool.free(_this.currTouch); + var listeners = _this.listeners; + for (var i_18 = 0; i_18 < listeners.length; i_18++) { + if (listeners[i_18].up) + listeners[i_18].up(x, y); + } + _this.lastX = x; + _this.lastY = y; + _this.buttonDown = false; + _this.currTouch = null; + break; + } + } + ev.preventDefault(); + }, false); + element.addEventListener("touchcancel", function (ev) { + var touches = ev.changedTouches; + for (var i = 0; i < touches.length; i++) { + var touch = touches[i]; + if (_this.currTouch.identifier === touch.identifier) { + var rect = element.getBoundingClientRect(); + var x = _this.currTouch.x = touch.clientX - rect.left; + var y = _this.currTouch.y = touch.clientY - rect.top; + _this.touchesPool.free(_this.currTouch); + var listeners = _this.listeners; + for (var i_19 = 0; i_19 < listeners.length; i_19++) { + if (listeners[i_19].up) + listeners[i_19].up(x, y); + } + _this.lastX = x; + _this.lastY = y; + _this.buttonDown = false; + _this.currTouch = null; + break; + } + } + ev.preventDefault(); + }, false); + element.addEventListener("touchmove", function (ev) { + if (_this.currTouch == null) + return; + var touches = ev.changedTouches; + for (var i = 0; i < touches.length; i++) { + var touch = touches[i]; + if (_this.currTouch.identifier === touch.identifier) { + var rect = element.getBoundingClientRect(); + var x = touch.clientX - rect.left; + var y = touch.clientY - rect.top; + var listeners = _this.listeners; + for (var i_20 = 0; i_20 < listeners.length; i_20++) { + if (listeners[i_20].dragged) + listeners[i_20].dragged(x, y); + } + _this.lastX = _this.currTouch.x = x; + _this.lastY = _this.currTouch.y = y; + break; + } + } + ev.preventDefault(); + }, false); + }; + Input.prototype.addListener = function (listener) { + this.listeners.push(listener); + }; + Input.prototype.removeListener = function (listener) { + var idx = this.listeners.indexOf(listener); + if (idx > -1) { + this.listeners.splice(idx, 1); + } + }; + return Input; + }()); + webgl.Input = Input; + var Touch = (function () { + function Touch(identifier, x, y) { + this.identifier = identifier; + this.x = x; + this.y = y; + } + return Touch; + }()); + webgl.Touch = Touch; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var LoadingScreen = (function () { + function LoadingScreen(renderer) { + this.logo = null; + this.spinner = null; + this.angle = 0; + this.fadeOut = 0; + this.timeKeeper = new spine.TimeKeeper(); + this.backgroundColor = new spine.Color(0.135, 0.135, 0.135, 1); + this.tempColor = new spine.Color(); + this.firstDraw = 0; + this.renderer = renderer; + this.timeKeeper.maxDelta = 9; + if (LoadingScreen.logoImg === null) { + var isSafari = navigator.userAgent.indexOf("Safari") > -1; + LoadingScreen.logoImg = new Image(); + LoadingScreen.logoImg.src = LoadingScreen.SPINE_LOGO_DATA; + if (!isSafari) + LoadingScreen.logoImg.crossOrigin = "anonymous"; + LoadingScreen.logoImg.onload = function (ev) { + LoadingScreen.loaded++; + }; + LoadingScreen.spinnerImg = new Image(); + LoadingScreen.spinnerImg.src = LoadingScreen.SPINNER_DATA; + if (!isSafari) + LoadingScreen.spinnerImg.crossOrigin = "anonymous"; + LoadingScreen.spinnerImg.onload = function (ev) { + LoadingScreen.loaded++; + }; + } + } + LoadingScreen.prototype.draw = function (complete) { + if (complete === void 0) { complete = false; } + if (complete && this.fadeOut > LoadingScreen.FADE_SECONDS) + return; + this.timeKeeper.update(); + var a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.75)); + this.angle -= this.timeKeeper.delta / 1.4 * 360 * (1 + 1.5 * Math.pow(a, 5)); + var renderer = this.renderer; + var canvas = renderer.canvas; + var gl = renderer.context.gl; + renderer.resize(webgl.ResizeMode.Stretch); + var oldX = renderer.camera.position.x, oldY = renderer.camera.position.y; + renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); + renderer.camera.viewportWidth = canvas.width; + renderer.camera.viewportHeight = canvas.height; + if (!complete) { + gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a); + gl.clear(gl.COLOR_BUFFER_BIT); + this.tempColor.a = 1; + } + else { + this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); + if (this.fadeOut > LoadingScreen.FADE_SECONDS) { + renderer.camera.position.set(oldX, oldY, 0); + return; + } + a = 1 - this.fadeOut / LoadingScreen.FADE_SECONDS; + this.tempColor.setFromColor(this.backgroundColor); + this.tempColor.a = 1 - (a - 1) * (a - 1); + renderer.begin(); + renderer.quad(true, 0, 0, canvas.width, 0, canvas.width, canvas.height, 0, canvas.height, this.tempColor, this.tempColor, this.tempColor, this.tempColor); + renderer.end(); + } + this.tempColor.set(1, 1, 1, this.tempColor.a); + if (LoadingScreen.loaded != 2) + return; + if (this.logo === null) { + this.logo = new webgl.GLTexture(renderer.context, LoadingScreen.logoImg); + this.spinner = new webgl.GLTexture(renderer.context, LoadingScreen.spinnerImg); + } + this.logo.update(false); + this.spinner.update(false); + var logoWidth = this.logo.getImage().width; + var logoHeight = this.logo.getImage().height; + var spinnerWidth = this.spinner.getImage().width; + var spinnerHeight = this.spinner.getImage().height; + renderer.batcher.setBlendMode(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + renderer.begin(); + renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, this.tempColor); + renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerWidth) / 2, (canvas.height - spinnerHeight) / 2, spinnerWidth, spinnerHeight, spinnerWidth / 2, spinnerHeight / 2, this.angle, this.tempColor); + renderer.end(); + renderer.camera.position.set(oldX, oldY, 0); + }; + LoadingScreen.FADE_SECONDS = 1; + LoadingScreen.loaded = 0; + LoadingScreen.spinnerImg = null; + LoadingScreen.logoImg = null; + LoadingScreen.SPINNER_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKMAAACjCAYAAADmbK6AAAAACXBIWXMAAAsTAAALEwEAmpwYAAALB2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIiB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNS41IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTYtMDktMDhUMTQ6MjU6MTIrMDI6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMTEtMTVUMTY6NDA6NTkrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE4LTExLTE1VDE2OjQwOjU5KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpmZDhlNTljMC02NGJjLTIxNGQtODAyZi1jZDlhODJjM2ZjMGMiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpmYmNmZWJlYS03MjY2LWE0NGQtOTI4NS0wOTJmNGNhYzk4ZWEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHRpZmY6T3JpZW50YXRpb249IjEiIHRpZmY6WFJlc29sdXRpb249IjcyMDAwMC8xMDAwMCIgdGlmZjpZUmVzb2x1dGlvbj0iNzIwMDAwLzEwMDAwIiB0aWZmOlJlc29sdXRpb25Vbml0PSIyIiBleGlmOkNvbG9yU3BhY2U9IjY1NTM1IiBleGlmOlBpeGVsWERpbWVuc2lvbj0iMjk3IiBleGlmOlBpeGVsWURpbWVuc2lvbj0iMjQyIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiIHN0RXZ0OndoZW49IjIwMTYtMDktMDhUMTQ6MjU6MTIrMDI6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1LjUgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiNThlMTlkNi0xYTRjLTQyNDEtODU0ZC01MDVlZjYxMjRhODQiIHN0RXZ0OndoZW49IjIwMTgtMTEtMTVUMTY6NDA6MjMrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjQ3YzYzYzIwLWJkYjgtYzM0YS1hYzMyLWQ5MDdjOWEyOTA0MCIgc3RFdnQ6d2hlbj0iMjAxOC0xMS0xNVQxNjo0MDo1OSswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY29udmVydGVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJkZXJpdmVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJjb252ZXJ0ZWQgZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZmQ4ZTU5YzAtNjRiYy0yMTRkLTgwMmYtY2Q5YTgyYzNmYzBjIiBzdEV2dDp3aGVuPSIyMDE4LTExLTE1VDE2OjQwOjU5KzAxOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0N2M2M2MyMC1iZGI4LWMzNGEtYWMzMi1kOTA3YzlhMjkwNDAiIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo2OWRmZjljYy01YzFiLWE5NDctOTc3OS03ODgxZjM0ODk3MDMiIHN0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiLz4gPHBob3Rvc2hvcDpEb2N1bWVudEFu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"; + LoadingScreen.SPINE_LOGO_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAABsCAYAAAALzHKmAAAACXBIWXMAAAsTAAALEwEAmpwYAAALB2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIiB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNS41IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTYtMDktMDhUMTQ6MjU6MTIrMDI6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMTEtMTVUMTY6NDA6NTkrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE4LTExLTE1VDE2OjQwOjU5KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowMTdhZGQ3Ni04OTZlLThlNGUtYmM5MS00ZjEyNjI1YjA3MjgiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDplMTViNGE2ZS1hMDg3LWEzNDktODdhOS1mNDYzYjE2MzQ0Y2MiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHRpZmY6T3JpZW50YXRpb249IjEiIHRpZmY6WFJlc29sdXRpb249IjcyMDAwMC8xMDAwMCIgdGlmZjpZUmVzb2x1dGlvbj0iNzIwMDAwLzEwMDAwIiB0aWZmOlJlc29sdXRpb25Vbml0PSIyIiBleGlmOkNvbG9yU3BhY2U9IjY1NTM1IiBleGlmOlBpeGVsWERpbWVuc2lvbj0iMjk3IiBleGlmOlBpeGVsWURpbWVuc2lvbj0iMjQyIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiIHN0RXZ0OndoZW49IjIwMTYtMDktMDhUMTQ6MjU6MTIrMDI6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1LjUgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiNThlMTlkNi0xYTRjLTQyNDEtODU0ZC01MDVlZjYxMjRhODQiIHN0RXZ0OndoZW49IjIwMTgtMTEtMTVUMTY6NDA6MjMrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjJlNjJiMWM2LWIxYzQtNDk0MC04MDMxLWU4ZDkyNTBmODJjNSIgc3RFdnQ6d2hlbj0iMjAxOC0xMS0xNVQxNjo0MDo1OSswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY29udmVydGVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJkZXJpdmVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJjb252ZXJ0ZWQgZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MDE3YWRkNzYtODk2ZS04ZTRlLWJjOTEtNGYxMjYyNWIwNzI4IiBzdEV2dDp3aGVuPSIyMDE4LTExLTE1VDE2OjQwOjU5KzAxOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZTYyYjFjNi1iMWM0LTQ5NDAtODAzMS1lOGQ5MjUwZjgyYzUiIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo2OWRmZjljYy01YzFiLWE5NDctOTc3OS03ODgxZjM0ODk3MDMiIHN0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowODMzNWIyYy04NzYyLWQzNGMtOTBhOS02ODJjYjJmYTQ2M2UiLz4gPHBob3Rvc2hvcDpEb2N1bWVudEFu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"; + return LoadingScreen; + }()); + webgl.LoadingScreen = LoadingScreen; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + webgl.M00 = 0; + webgl.M01 = 4; + webgl.M02 = 8; + webgl.M03 = 12; + webgl.M10 = 1; + webgl.M11 = 5; + webgl.M12 = 9; + webgl.M13 = 13; + webgl.M20 = 2; + webgl.M21 = 6; + webgl.M22 = 10; + webgl.M23 = 14; + webgl.M30 = 3; + webgl.M31 = 7; + webgl.M32 = 11; + webgl.M33 = 15; + var Matrix4 = (function () { + function Matrix4() { + this.temp = new Float32Array(16); + this.values = new Float32Array(16); + var v = this.values; + v[webgl.M00] = 1; + v[webgl.M11] = 1; + v[webgl.M22] = 1; + v[webgl.M33] = 1; + } + Matrix4.prototype.set = function (values) { + this.values.set(values); + return this; + }; + Matrix4.prototype.transpose = function () { + var t = this.temp; + var v = this.values; + t[webgl.M00] = v[webgl.M00]; + t[webgl.M01] = v[webgl.M10]; + t[webgl.M02] = v[webgl.M20]; + t[webgl.M03] = v[webgl.M30]; + t[webgl.M10] = v[webgl.M01]; + t[webgl.M11] = v[webgl.M11]; + t[webgl.M12] = v[webgl.M21]; + t[webgl.M13] = v[webgl.M31]; + t[webgl.M20] = v[webgl.M02]; + t[webgl.M21] = v[webgl.M12]; + t[webgl.M22] = v[webgl.M22]; + t[webgl.M23] = v[webgl.M32]; + t[webgl.M30] = v[webgl.M03]; + t[webgl.M31] = v[webgl.M13]; + t[webgl.M32] = v[webgl.M23]; + t[webgl.M33] = v[webgl.M33]; + return this.set(t); + }; + Matrix4.prototype.identity = function () { + var v = this.values; + v[webgl.M00] = 1; + v[webgl.M01] = 0; + v[webgl.M02] = 0; + v[webgl.M03] = 0; + v[webgl.M10] = 0; + v[webgl.M11] = 1; + v[webgl.M12] = 0; + v[webgl.M13] = 0; + v[webgl.M20] = 0; + v[webgl.M21] = 0; + v[webgl.M22] = 1; + v[webgl.M23] = 0; + v[webgl.M30] = 0; + v[webgl.M31] = 0; + v[webgl.M32] = 0; + v[webgl.M33] = 1; + return this; + }; + Matrix4.prototype.invert = function () { + var v = this.values; + var t = this.temp; + var l_det = v[webgl.M30] * v[webgl.M21] * v[webgl.M12] * v[webgl.M03] - v[webgl.M20] * v[webgl.M31] * v[webgl.M12] * v[webgl.M03] - v[webgl.M30] * v[webgl.M11] * v[webgl.M22] * v[webgl.M03] + + v[webgl.M10] * v[webgl.M31] * v[webgl.M22] * v[webgl.M03] + v[webgl.M20] * v[webgl.M11] * v[webgl.M32] * v[webgl.M03] - v[webgl.M10] * v[webgl.M21] * v[webgl.M32] * v[webgl.M03] + - v[webgl.M30] * v[webgl.M21] * v[webgl.M02] * v[webgl.M13] + v[webgl.M20] * v[webgl.M31] * v[webgl.M02] * v[webgl.M13] + v[webgl.M30] * v[webgl.M01] * v[webgl.M22] * v[webgl.M13] + - v[webgl.M00] * v[webgl.M31] * v[webgl.M22] * v[webgl.M13] - v[webgl.M20] * v[webgl.M01] * v[webgl.M32] * v[webgl.M13] + v[webgl.M00] * v[webgl.M21] * v[webgl.M32] * v[webgl.M13] + + v[webgl.M30] * v[webgl.M11] * v[webgl.M02] * v[webgl.M23] - v[webgl.M10] * v[webgl.M31] * v[webgl.M02] * v[webgl.M23] - v[webgl.M30] * v[webgl.M01] * v[webgl.M12] * v[webgl.M23] + + v[webgl.M00] * v[webgl.M31] * v[webgl.M12] * v[webgl.M23] + v[webgl.M10] * v[webgl.M01] * v[webgl.M32] * v[webgl.M23] - v[webgl.M00] * v[webgl.M11] * v[webgl.M32] * v[webgl.M23] + - v[webgl.M20] * v[webgl.M11] * v[webgl.M02] * v[webgl.M33] + v[webgl.M10] * v[webgl.M21] * v[webgl.M02] * v[webgl.M33] + v[webgl.M20] * v[webgl.M01] * v[webgl.M12] * v[webgl.M33] + - v[webgl.M00] * v[webgl.M21] * v[webgl.M12] * v[webgl.M33] - v[webgl.M10] * v[webgl.M01] * v[webgl.M22] * v[webgl.M33] + v[webgl.M00] * v[webgl.M11] * v[webgl.M22] * v[webgl.M33]; + if (l_det == 0) + throw new Error("non-invertible matrix"); + var inv_det = 1.0 / l_det; + t[webgl.M00] = v[webgl.M12] * v[webgl.M23] * v[webgl.M31] - v[webgl.M13] * v[webgl.M22] * v[webgl.M31] + v[webgl.M13] * v[webgl.M21] * v[webgl.M32] + - v[webgl.M11] * v[webgl.M23] * v[webgl.M32] - v[webgl.M12] * v[webgl.M21] * v[webgl.M33] + v[webgl.M11] * v[webgl.M22] * v[webgl.M33]; + t[webgl.M01] = v[webgl.M03] * v[webgl.M22] * v[webgl.M31] - v[webgl.M02] * v[webgl.M23] * v[webgl.M31] - v[webgl.M03] * v[webgl.M21] * v[webgl.M32] + + v[webgl.M01] * v[webgl.M23] * v[webgl.M32] + v[webgl.M02] * v[webgl.M21] * v[webgl.M33] - v[webgl.M01] * v[webgl.M22] * v[webgl.M33]; + t[webgl.M02] = v[webgl.M02] * v[webgl.M13] * v[webgl.M31] - v[webgl.M03] * v[webgl.M12] * v[webgl.M31] + v[webgl.M03] * v[webgl.M11] * v[webgl.M32] + - v[webgl.M01] * v[webgl.M13] * v[webgl.M32] - v[webgl.M02] * v[webgl.M11] * v[webgl.M33] + v[webgl.M01] * v[webgl.M12] * v[webgl.M33]; + t[webgl.M03] = v[webgl.M03] * v[webgl.M12] * v[webgl.M21] - v[webgl.M02] * v[webgl.M13] * v[webgl.M21] - v[webgl.M03] * v[webgl.M11] * v[webgl.M22] + + v[webgl.M01] * v[webgl.M13] * v[webgl.M22] + v[webgl.M02] * v[webgl.M11] * v[webgl.M23] - v[webgl.M01] * v[webgl.M12] * v[webgl.M23]; + t[webgl.M10] = v[webgl.M13] * v[webgl.M22] * v[webgl.M30] - v[webgl.M12] * v[webgl.M23] * v[webgl.M30] - v[webgl.M13] * v[webgl.M20] * v[webgl.M32] + + v[webgl.M10] * v[webgl.M23] * v[webgl.M32] + v[webgl.M12] * v[webgl.M20] * v[webgl.M33] - v[webgl.M10] * v[webgl.M22] * v[webgl.M33]; + t[webgl.M11] = v[webgl.M02] * v[webgl.M23] * v[webgl.M30] - v[webgl.M03] * v[webgl.M22] * v[webgl.M30] + v[webgl.M03] * v[webgl.M20] * v[webgl.M32] + - v[webgl.M00] * v[webgl.M23] * v[webgl.M32] - v[webgl.M02] * v[webgl.M20] * v[webgl.M33] + v[webgl.M00] * v[webgl.M22] * v[webgl.M33]; + t[webgl.M12] = v[webgl.M03] * v[webgl.M12] * v[webgl.M30] - v[webgl.M02] * v[webgl.M13] * v[webgl.M30] - v[webgl.M03] * v[webgl.M10] * v[webgl.M32] + + v[webgl.M00] * v[webgl.M13] * v[webgl.M32] + v[webgl.M02] * v[webgl.M10] * v[webgl.M33] - v[webgl.M00] * v[webgl.M12] * v[webgl.M33]; + t[webgl.M13] = v[webgl.M02] * v[webgl.M13] * v[webgl.M20] - v[webgl.M03] * v[webgl.M12] * v[webgl.M20] + v[webgl.M03] * v[webgl.M10] * v[webgl.M22] + - v[webgl.M00] * v[webgl.M13] * v[webgl.M22] - v[webgl.M02] * v[webgl.M10] * v[webgl.M23] + v[webgl.M00] * v[webgl.M12] * v[webgl.M23]; + t[webgl.M20] = v[webgl.M11] * v[webgl.M23] * v[webgl.M30] - v[webgl.M13] * v[webgl.M21] * v[webgl.M30] + v[webgl.M13] * v[webgl.M20] * v[webgl.M31] + - v[webgl.M10] * v[webgl.M23] * v[webgl.M31] - v[webgl.M11] * v[webgl.M20] * v[webgl.M33] + v[webgl.M10] * v[webgl.M21] * v[webgl.M33]; + t[webgl.M21] = v[webgl.M03] * v[webgl.M21] * v[webgl.M30] - v[webgl.M01] * v[webgl.M23] * v[webgl.M30] - v[webgl.M03] * v[webgl.M20] * v[webgl.M31] + + v[webgl.M00] * v[webgl.M23] * v[webgl.M31] + v[webgl.M01] * v[webgl.M20] * v[webgl.M33] - v[webgl.M00] * v[webgl.M21] * v[webgl.M33]; + t[webgl.M22] = v[webgl.M01] * v[webgl.M13] * v[webgl.M30] - v[webgl.M03] * v[webgl.M11] * v[webgl.M30] + v[webgl.M03] * v[webgl.M10] * v[webgl.M31] + - v[webgl.M00] * v[webgl.M13] * v[webgl.M31] - v[webgl.M01] * v[webgl.M10] * v[webgl.M33] + v[webgl.M00] * v[webgl.M11] * v[webgl.M33]; + t[webgl.M23] = v[webgl.M03] * v[webgl.M11] * v[webgl.M20] - v[webgl.M01] * v[webgl.M13] * v[webgl.M20] - v[webgl.M03] * v[webgl.M10] * v[webgl.M21] + + v[webgl.M00] * v[webgl.M13] * v[webgl.M21] + v[webgl.M01] * v[webgl.M10] * v[webgl.M23] - v[webgl.M00] * v[webgl.M11] * v[webgl.M23]; + t[webgl.M30] = v[webgl.M12] * v[webgl.M21] * v[webgl.M30] - v[webgl.M11] * v[webgl.M22] * v[webgl.M30] - v[webgl.M12] * v[webgl.M20] * v[webgl.M31] + + v[webgl.M10] * v[webgl.M22] * v[webgl.M31] + v[webgl.M11] * v[webgl.M20] * v[webgl.M32] - v[webgl.M10] * v[webgl.M21] * v[webgl.M32]; + t[webgl.M31] = v[webgl.M01] * v[webgl.M22] * v[webgl.M30] - v[webgl.M02] * v[webgl.M21] * v[webgl.M30] + v[webgl.M02] * v[webgl.M20] * v[webgl.M31] + - v[webgl.M00] * v[webgl.M22] * v[webgl.M31] - v[webgl.M01] * v[webgl.M20] * v[webgl.M32] + v[webgl.M00] * v[webgl.M21] * v[webgl.M32]; + t[webgl.M32] = v[webgl.M02] * v[webgl.M11] * v[webgl.M30] - v[webgl.M01] * v[webgl.M12] * v[webgl.M30] - v[webgl.M02] * v[webgl.M10] * v[webgl.M31] + + v[webgl.M00] * v[webgl.M12] * v[webgl.M31] + v[webgl.M01] * v[webgl.M10] * v[webgl.M32] - v[webgl.M00] * v[webgl.M11] * v[webgl.M32]; + t[webgl.M33] = v[webgl.M01] * v[webgl.M12] * v[webgl.M20] - v[webgl.M02] * v[webgl.M11] * v[webgl.M20] + v[webgl.M02] * v[webgl.M10] * v[webgl.M21] + - v[webgl.M00] * v[webgl.M12] * v[webgl.M21] - v[webgl.M01] * v[webgl.M10] * v[webgl.M22] + v[webgl.M00] * v[webgl.M11] * v[webgl.M22]; + v[webgl.M00] = t[webgl.M00] * inv_det; + v[webgl.M01] = t[webgl.M01] * inv_det; + v[webgl.M02] = t[webgl.M02] * inv_det; + v[webgl.M03] = t[webgl.M03] * inv_det; + v[webgl.M10] = t[webgl.M10] * inv_det; + v[webgl.M11] = t[webgl.M11] * inv_det; + v[webgl.M12] = t[webgl.M12] * inv_det; + v[webgl.M13] = t[webgl.M13] * inv_det; + v[webgl.M20] = t[webgl.M20] * inv_det; + v[webgl.M21] = t[webgl.M21] * inv_det; + v[webgl.M22] = t[webgl.M22] * inv_det; + v[webgl.M23] = t[webgl.M23] * inv_det; + v[webgl.M30] = t[webgl.M30] * inv_det; + v[webgl.M31] = t[webgl.M31] * inv_det; + v[webgl.M32] = t[webgl.M32] * inv_det; + v[webgl.M33] = t[webgl.M33] * inv_det; + return this; + }; + Matrix4.prototype.determinant = function () { + var v = this.values; + return v[webgl.M30] * v[webgl.M21] * v[webgl.M12] * v[webgl.M03] - v[webgl.M20] * v[webgl.M31] * v[webgl.M12] * v[webgl.M03] - v[webgl.M30] * v[webgl.M11] * v[webgl.M22] * v[webgl.M03] + + v[webgl.M10] * v[webgl.M31] * v[webgl.M22] * v[webgl.M03] + v[webgl.M20] * v[webgl.M11] * v[webgl.M32] * v[webgl.M03] - v[webgl.M10] * v[webgl.M21] * v[webgl.M32] * v[webgl.M03] + - v[webgl.M30] * v[webgl.M21] * v[webgl.M02] * v[webgl.M13] + v[webgl.M20] * v[webgl.M31] * v[webgl.M02] * v[webgl.M13] + v[webgl.M30] * v[webgl.M01] * v[webgl.M22] * v[webgl.M13] + - v[webgl.M00] * v[webgl.M31] * v[webgl.M22] * v[webgl.M13] - v[webgl.M20] * v[webgl.M01] * v[webgl.M32] * v[webgl.M13] + v[webgl.M00] * v[webgl.M21] * v[webgl.M32] * v[webgl.M13] + + v[webgl.M30] * v[webgl.M11] * v[webgl.M02] * v[webgl.M23] - v[webgl.M10] * v[webgl.M31] * v[webgl.M02] * v[webgl.M23] - v[webgl.M30] * v[webgl.M01] * v[webgl.M12] * v[webgl.M23] + + v[webgl.M00] * v[webgl.M31] * v[webgl.M12] * v[webgl.M23] + v[webgl.M10] * v[webgl.M01] * v[webgl.M32] * v[webgl.M23] - v[webgl.M00] * v[webgl.M11] * v[webgl.M32] * v[webgl.M23] + - v[webgl.M20] * v[webgl.M11] * v[webgl.M02] * v[webgl.M33] + v[webgl.M10] * v[webgl.M21] * v[webgl.M02] * v[webgl.M33] + v[webgl.M20] * v[webgl.M01] * v[webgl.M12] * v[webgl.M33] + - v[webgl.M00] * v[webgl.M21] * v[webgl.M12] * v[webgl.M33] - v[webgl.M10] * v[webgl.M01] * v[webgl.M22] * v[webgl.M33] + v[webgl.M00] * v[webgl.M11] * v[webgl.M22] * v[webgl.M33]; + }; + Matrix4.prototype.translate = function (x, y, z) { + var v = this.values; + v[webgl.M03] += x; + v[webgl.M13] += y; + v[webgl.M23] += z; + return this; + }; + Matrix4.prototype.copy = function () { + return new Matrix4().set(this.values); + }; + Matrix4.prototype.projection = function (near, far, fovy, aspectRatio) { + this.identity(); + var l_fd = (1.0 / Math.tan((fovy * (Math.PI / 180)) / 2.0)); + var l_a1 = (far + near) / (near - far); + var l_a2 = (2 * far * near) / (near - far); + var v = this.values; + v[webgl.M00] = l_fd / aspectRatio; + v[webgl.M10] = 0; + v[webgl.M20] = 0; + v[webgl.M30] = 0; + v[webgl.M01] = 0; + v[webgl.M11] = l_fd; + v[webgl.M21] = 0; + v[webgl.M31] = 0; + v[webgl.M02] = 0; + v[webgl.M12] = 0; + v[webgl.M22] = l_a1; + v[webgl.M32] = -1; + v[webgl.M03] = 0; + v[webgl.M13] = 0; + v[webgl.M23] = l_a2; + v[webgl.M33] = 0; + return this; + }; + Matrix4.prototype.ortho2d = function (x, y, width, height) { + return this.ortho(x, x + width, y, y + height, 0, 1); + }; + Matrix4.prototype.ortho = function (left, right, bottom, top, near, far) { + this.identity(); + var x_orth = 2 / (right - left); + var y_orth = 2 / (top - bottom); + var z_orth = -2 / (far - near); + var tx = -(right + left) / (right - left); + var ty = -(top + bottom) / (top - bottom); + var tz = -(far + near) / (far - near); + var v = this.values; + v[webgl.M00] = x_orth; + v[webgl.M10] = 0; + v[webgl.M20] = 0; + v[webgl.M30] = 0; + v[webgl.M01] = 0; + v[webgl.M11] = y_orth; + v[webgl.M21] = 0; + v[webgl.M31] = 0; + v[webgl.M02] = 0; + v[webgl.M12] = 0; + v[webgl.M22] = z_orth; + v[webgl.M32] = 0; + v[webgl.M03] = tx; + v[webgl.M13] = ty; + v[webgl.M23] = tz; + v[webgl.M33] = 1; + return this; + }; + Matrix4.prototype.multiply = function (matrix) { + var t = this.temp; + var v = this.values; + var m = matrix.values; + t[webgl.M00] = v[webgl.M00] * m[webgl.M00] + v[webgl.M01] * m[webgl.M10] + v[webgl.M02] * m[webgl.M20] + v[webgl.M03] * m[webgl.M30]; + t[webgl.M01] = v[webgl.M00] * m[webgl.M01] + v[webgl.M01] * m[webgl.M11] + v[webgl.M02] * m[webgl.M21] + v[webgl.M03] * m[webgl.M31]; + t[webgl.M02] = v[webgl.M00] * m[webgl.M02] + v[webgl.M01] * m[webgl.M12] + v[webgl.M02] * m[webgl.M22] + v[webgl.M03] * m[webgl.M32]; + t[webgl.M03] = v[webgl.M00] * m[webgl.M03] + v[webgl.M01] * m[webgl.M13] + v[webgl.M02] * m[webgl.M23] + v[webgl.M03] * m[webgl.M33]; + t[webgl.M10] = v[webgl.M10] * m[webgl.M00] + v[webgl.M11] * m[webgl.M10] + v[webgl.M12] * m[webgl.M20] + v[webgl.M13] * m[webgl.M30]; + t[webgl.M11] = v[webgl.M10] * m[webgl.M01] + v[webgl.M11] * m[webgl.M11] + v[webgl.M12] * m[webgl.M21] + v[webgl.M13] * m[webgl.M31]; + t[webgl.M12] = v[webgl.M10] * m[webgl.M02] + v[webgl.M11] * m[webgl.M12] + v[webgl.M12] * m[webgl.M22] + v[webgl.M13] * m[webgl.M32]; + t[webgl.M13] = v[webgl.M10] * m[webgl.M03] + v[webgl.M11] * m[webgl.M13] + v[webgl.M12] * m[webgl.M23] + v[webgl.M13] * m[webgl.M33]; + t[webgl.M20] = v[webgl.M20] * m[webgl.M00] + v[webgl.M21] * m[webgl.M10] + v[webgl.M22] * m[webgl.M20] + v[webgl.M23] * m[webgl.M30]; + t[webgl.M21] = v[webgl.M20] * m[webgl.M01] + v[webgl.M21] * m[webgl.M11] + v[webgl.M22] * m[webgl.M21] + v[webgl.M23] * m[webgl.M31]; + t[webgl.M22] = v[webgl.M20] * m[webgl.M02] + v[webgl.M21] * m[webgl.M12] + v[webgl.M22] * m[webgl.M22] + v[webgl.M23] * m[webgl.M32]; + t[webgl.M23] = v[webgl.M20] * m[webgl.M03] + v[webgl.M21] * m[webgl.M13] + v[webgl.M22] * m[webgl.M23] + v[webgl.M23] * m[webgl.M33]; + t[webgl.M30] = v[webgl.M30] * m[webgl.M00] + v[webgl.M31] * m[webgl.M10] + v[webgl.M32] * m[webgl.M20] + v[webgl.M33] * m[webgl.M30]; + t[webgl.M31] = v[webgl.M30] * m[webgl.M01] + v[webgl.M31] * m[webgl.M11] + v[webgl.M32] * m[webgl.M21] + v[webgl.M33] * m[webgl.M31]; + t[webgl.M32] = v[webgl.M30] * m[webgl.M02] + v[webgl.M31] * m[webgl.M12] + v[webgl.M32] * m[webgl.M22] + v[webgl.M33] * m[webgl.M32]; + t[webgl.M33] = v[webgl.M30] * m[webgl.M03] + v[webgl.M31] * m[webgl.M13] + v[webgl.M32] * m[webgl.M23] + v[webgl.M33] * m[webgl.M33]; + return this.set(this.temp); + }; + Matrix4.prototype.multiplyLeft = function (matrix) { + var t = this.temp; + var v = this.values; + var m = matrix.values; + t[webgl.M00] = m[webgl.M00] * v[webgl.M00] + m[webgl.M01] * v[webgl.M10] + m[webgl.M02] * v[webgl.M20] + m[webgl.M03] * v[webgl.M30]; + t[webgl.M01] = m[webgl.M00] * v[webgl.M01] + m[webgl.M01] * v[webgl.M11] + m[webgl.M02] * v[webgl.M21] + m[webgl.M03] * v[webgl.M31]; + t[webgl.M02] = m[webgl.M00] * v[webgl.M02] + m[webgl.M01] * v[webgl.M12] + m[webgl.M02] * v[webgl.M22] + m[webgl.M03] * v[webgl.M32]; + t[webgl.M03] = m[webgl.M00] * v[webgl.M03] + m[webgl.M01] * v[webgl.M13] + m[webgl.M02] * v[webgl.M23] + m[webgl.M03] * v[webgl.M33]; + t[webgl.M10] = m[webgl.M10] * v[webgl.M00] + m[webgl.M11] * v[webgl.M10] + m[webgl.M12] * v[webgl.M20] + m[webgl.M13] * v[webgl.M30]; + t[webgl.M11] = m[webgl.M10] * v[webgl.M01] + m[webgl.M11] * v[webgl.M11] + m[webgl.M12] * v[webgl.M21] + m[webgl.M13] * v[webgl.M31]; + t[webgl.M12] = m[webgl.M10] * v[webgl.M02] + m[webgl.M11] * v[webgl.M12] + m[webgl.M12] * v[webgl.M22] + m[webgl.M13] * v[webgl.M32]; + t[webgl.M13] = m[webgl.M10] * v[webgl.M03] + m[webgl.M11] * v[webgl.M13] + m[webgl.M12] * v[webgl.M23] + m[webgl.M13] * v[webgl.M33]; + t[webgl.M20] = m[webgl.M20] * v[webgl.M00] + m[webgl.M21] * v[webgl.M10] + m[webgl.M22] * v[webgl.M20] + m[webgl.M23] * v[webgl.M30]; + t[webgl.M21] = m[webgl.M20] * v[webgl.M01] + m[webgl.M21] * v[webgl.M11] + m[webgl.M22] * v[webgl.M21] + m[webgl.M23] * v[webgl.M31]; + t[webgl.M22] = m[webgl.M20] * v[webgl.M02] + m[webgl.M21] * v[webgl.M12] + m[webgl.M22] * v[webgl.M22] + m[webgl.M23] * v[webgl.M32]; + t[webgl.M23] = m[webgl.M20] * v[webgl.M03] + m[webgl.M21] * v[webgl.M13] + m[webgl.M22] * v[webgl.M23] + m[webgl.M23] * v[webgl.M33]; + t[webgl.M30] = m[webgl.M30] * v[webgl.M00] + m[webgl.M31] * v[webgl.M10] + m[webgl.M32] * v[webgl.M20] + m[webgl.M33] * v[webgl.M30]; + t[webgl.M31] = m[webgl.M30] * v[webgl.M01] + m[webgl.M31] * v[webgl.M11] + m[webgl.M32] * v[webgl.M21] + m[webgl.M33] * v[webgl.M31]; + t[webgl.M32] = m[webgl.M30] * v[webgl.M02] + m[webgl.M31] * v[webgl.M12] + m[webgl.M32] * v[webgl.M22] + m[webgl.M33] * v[webgl.M32]; + t[webgl.M33] = m[webgl.M30] * v[webgl.M03] + m[webgl.M31] * v[webgl.M13] + m[webgl.M32] * v[webgl.M23] + m[webgl.M33] * v[webgl.M33]; + return this.set(this.temp); + }; + Matrix4.prototype.lookAt = function (position, direction, up) { + Matrix4.initTemps(); + var xAxis = Matrix4.xAxis, yAxis = Matrix4.yAxis, zAxis = Matrix4.zAxis; + zAxis.setFrom(direction).normalize(); + xAxis.setFrom(direction).normalize(); + xAxis.cross(up).normalize(); + yAxis.setFrom(xAxis).cross(zAxis).normalize(); + this.identity(); + var val = this.values; + val[webgl.M00] = xAxis.x; + val[webgl.M01] = xAxis.y; + val[webgl.M02] = xAxis.z; + val[webgl.M10] = yAxis.x; + val[webgl.M11] = yAxis.y; + val[webgl.M12] = yAxis.z; + val[webgl.M20] = -zAxis.x; + val[webgl.M21] = -zAxis.y; + val[webgl.M22] = -zAxis.z; + Matrix4.tmpMatrix.identity(); + Matrix4.tmpMatrix.values[webgl.M03] = -position.x; + Matrix4.tmpMatrix.values[webgl.M13] = -position.y; + Matrix4.tmpMatrix.values[webgl.M23] = -position.z; + this.multiply(Matrix4.tmpMatrix); + return this; + }; + Matrix4.initTemps = function () { + if (Matrix4.xAxis === null) + Matrix4.xAxis = new webgl.Vector3(); + if (Matrix4.yAxis === null) + Matrix4.yAxis = new webgl.Vector3(); + if (Matrix4.zAxis === null) + Matrix4.zAxis = new webgl.Vector3(); + }; + Matrix4.xAxis = null; + Matrix4.yAxis = null; + Matrix4.zAxis = null; + Matrix4.tmpMatrix = new Matrix4(); + return Matrix4; + }()); + webgl.Matrix4 = Matrix4; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var Mesh = (function () { + function Mesh(context, attributes, maxVertices, maxIndices) { + this.attributes = attributes; + this.verticesLength = 0; + this.dirtyVertices = false; + this.indicesLength = 0; + this.dirtyIndices = false; + this.elementsPerVertex = 0; + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + this.elementsPerVertex = 0; + for (var i = 0; i < attributes.length; i++) { + this.elementsPerVertex += attributes[i].numElements; + } + this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); + this.indices = new Uint16Array(maxIndices); + this.context.addRestorable(this); + } + Mesh.prototype.getAttributes = function () { return this.attributes; }; + Mesh.prototype.maxVertices = function () { return this.vertices.length / this.elementsPerVertex; }; + Mesh.prototype.numVertices = function () { return this.verticesLength / this.elementsPerVertex; }; + Mesh.prototype.setVerticesLength = function (length) { + this.dirtyVertices = true; + this.verticesLength = length; + }; + Mesh.prototype.getVertices = function () { return this.vertices; }; + Mesh.prototype.maxIndices = function () { return this.indices.length; }; + Mesh.prototype.numIndices = function () { return this.indicesLength; }; + Mesh.prototype.setIndicesLength = function (length) { + this.dirtyIndices = true; + this.indicesLength = length; + }; + Mesh.prototype.getIndices = function () { return this.indices; }; + ; + Mesh.prototype.getVertexSizeInFloats = function () { + var size = 0; + for (var i = 0; i < this.attributes.length; i++) { + var attribute = this.attributes[i]; + size += attribute.numElements; + } + return size; + }; + Mesh.prototype.setVertices = function (vertices) { + this.dirtyVertices = true; + if (vertices.length > this.vertices.length) + throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); + this.vertices.set(vertices, 0); + this.verticesLength = vertices.length; + }; + Mesh.prototype.setIndices = function (indices) { + this.dirtyIndices = true; + if (indices.length > this.indices.length) + throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); + this.indices.set(indices, 0); + this.indicesLength = indices.length; + }; + Mesh.prototype.draw = function (shader, primitiveType) { + this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); + }; + Mesh.prototype.drawWithOffset = function (shader, primitiveType, offset, count) { + var gl = this.context.gl; + if (this.dirtyVertices || this.dirtyIndices) + this.update(); + this.bind(shader); + if (this.indicesLength > 0) { + gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); + } + else { + gl.drawArrays(primitiveType, offset, count); + } + this.unbind(shader); + }; + Mesh.prototype.bind = function (shader) { + var gl = this.context.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + var offset = 0; + for (var i = 0; i < this.attributes.length; i++) { + var attrib = this.attributes[i]; + var location_1 = shader.getAttributeLocation(attrib.name); + gl.enableVertexAttribArray(location_1); + gl.vertexAttribPointer(location_1, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); + offset += attrib.numElements; + } + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + }; + Mesh.prototype.unbind = function (shader) { + var gl = this.context.gl; + for (var i = 0; i < this.attributes.length; i++) { + var attrib = this.attributes[i]; + var location_2 = shader.getAttributeLocation(attrib.name); + gl.disableVertexAttribArray(location_2); + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + }; + Mesh.prototype.update = function () { + var gl = this.context.gl; + if (this.dirtyVertices) { + if (!this.verticesBuffer) { + this.verticesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); + this.dirtyVertices = false; + } + if (this.dirtyIndices) { + if (!this.indicesBuffer) { + this.indicesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); + this.dirtyIndices = false; + } + }; + Mesh.prototype.restore = function () { + this.verticesBuffer = null; + this.indicesBuffer = null; + this.update(); + }; + Mesh.prototype.dispose = function () { + this.context.removeRestorable(this); + var gl = this.context.gl; + gl.deleteBuffer(this.verticesBuffer); + gl.deleteBuffer(this.indicesBuffer); + }; + return Mesh; + }()); + webgl.Mesh = Mesh; + var VertexAttribute = (function () { + function VertexAttribute(name, type, numElements) { + this.name = name; + this.type = type; + this.numElements = numElements; + } + return VertexAttribute; + }()); + webgl.VertexAttribute = VertexAttribute; + var Position2Attribute = (function (_super) { + __extends(Position2Attribute, _super); + function Position2Attribute() { + return _super.call(this, webgl.Shader.POSITION, VertexAttributeType.Float, 2) || this; + } + return Position2Attribute; + }(VertexAttribute)); + webgl.Position2Attribute = Position2Attribute; + var Position3Attribute = (function (_super) { + __extends(Position3Attribute, _super); + function Position3Attribute() { + return _super.call(this, webgl.Shader.POSITION, VertexAttributeType.Float, 3) || this; + } + return Position3Attribute; + }(VertexAttribute)); + webgl.Position3Attribute = Position3Attribute; + var TexCoordAttribute = (function (_super) { + __extends(TexCoordAttribute, _super); + function TexCoordAttribute(unit) { + if (unit === void 0) { unit = 0; } + return _super.call(this, webgl.Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2) || this; + } + return TexCoordAttribute; + }(VertexAttribute)); + webgl.TexCoordAttribute = TexCoordAttribute; + var ColorAttribute = (function (_super) { + __extends(ColorAttribute, _super); + function ColorAttribute() { + return _super.call(this, webgl.Shader.COLOR, VertexAttributeType.Float, 4) || this; + } + return ColorAttribute; + }(VertexAttribute)); + webgl.ColorAttribute = ColorAttribute; + var Color2Attribute = (function (_super) { + __extends(Color2Attribute, _super); + function Color2Attribute() { + return _super.call(this, webgl.Shader.COLOR2, VertexAttributeType.Float, 4) || this; + } + return Color2Attribute; + }(VertexAttribute)); + webgl.Color2Attribute = Color2Attribute; + var VertexAttributeType; + (function (VertexAttributeType) { + VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float"; + })(VertexAttributeType = webgl.VertexAttributeType || (webgl.VertexAttributeType = {})); + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var PolygonBatcher = (function () { + function PolygonBatcher(context, twoColorTint, maxVertices) { + if (twoColorTint === void 0) { twoColorTint = true; } + if (maxVertices === void 0) { maxVertices = 10920; } + this.isDrawing = false; + this.shader = null; + this.lastTexture = null; + this.verticesLength = 0; + this.indicesLength = 0; + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + var attributes = twoColorTint ? + [new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute(), new webgl.Color2Attribute()] : + [new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()]; + this.mesh = new webgl.Mesh(context, attributes, maxVertices, maxVertices * 3); + this.srcBlend = this.context.gl.SRC_ALPHA; + this.dstBlend = this.context.gl.ONE_MINUS_SRC_ALPHA; + } + PolygonBatcher.prototype.begin = function (shader) { + var gl = this.context.gl; + if (this.isDrawing) + throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()"); + this.drawCalls = 0; + this.shader = shader; + this.lastTexture = null; + this.isDrawing = true; + gl.enable(gl.BLEND); + gl.blendFunc(this.srcBlend, this.dstBlend); + }; + PolygonBatcher.prototype.setBlendMode = function (srcBlend, dstBlend) { + var gl = this.context.gl; + this.srcBlend = srcBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + gl.blendFunc(this.srcBlend, this.dstBlend); + } + }; + PolygonBatcher.prototype.draw = function (texture, vertices, indices) { + if (texture != this.lastTexture) { + this.flush(); + this.lastTexture = texture; + } + else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || + this.indicesLength + indices.length > this.mesh.getIndices().length) { + this.flush(); + } + var indexStart = this.mesh.numVertices(); + this.mesh.getVertices().set(vertices, this.verticesLength); + this.verticesLength += vertices.length; + this.mesh.setVerticesLength(this.verticesLength); + var indicesArray = this.mesh.getIndices(); + for (var i = this.indicesLength, j = 0; j < indices.length; i++, j++) + indicesArray[i] = indices[j] + indexStart; + this.indicesLength += indices.length; + this.mesh.setIndicesLength(this.indicesLength); + }; + PolygonBatcher.prototype.flush = function () { + var gl = this.context.gl; + if (this.verticesLength == 0) + return; + this.lastTexture.bind(); + this.mesh.draw(this.shader, gl.TRIANGLES); + this.verticesLength = 0; + this.indicesLength = 0; + this.mesh.setVerticesLength(0); + this.mesh.setIndicesLength(0); + this.drawCalls++; + }; + PolygonBatcher.prototype.end = function () { + var gl = this.context.gl; + if (!this.isDrawing) + throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()"); + if (this.verticesLength > 0 || this.indicesLength > 0) + this.flush(); + this.shader = null; + this.lastTexture = null; + this.isDrawing = false; + gl.disable(gl.BLEND); + }; + PolygonBatcher.prototype.getDrawCalls = function () { return this.drawCalls; }; + PolygonBatcher.prototype.dispose = function () { + this.mesh.dispose(); + }; + return PolygonBatcher; + }()); + webgl.PolygonBatcher = PolygonBatcher; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var SceneRenderer = (function () { + function SceneRenderer(canvas, context, twoColorTint) { + if (twoColorTint === void 0) { twoColorTint = true; } + this.twoColorTint = false; + this.activeRenderer = null; + this.QUAD = [ + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + ]; + this.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + this.WHITE = new spine.Color(1, 1, 1, 1); + this.canvas = canvas; + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + this.twoColorTint = twoColorTint; + this.camera = new webgl.OrthoCamera(canvas.width, canvas.height); + this.batcherShader = twoColorTint ? webgl.Shader.newTwoColoredTextured(this.context) : webgl.Shader.newColoredTextured(this.context); + this.batcher = new webgl.PolygonBatcher(this.context, twoColorTint); + this.shapesShader = webgl.Shader.newColored(this.context); + this.shapes = new webgl.ShapeRenderer(this.context); + this.skeletonRenderer = new webgl.SkeletonRenderer(this.context, twoColorTint); + this.skeletonDebugRenderer = new webgl.SkeletonDebugRenderer(this.context); + } + SceneRenderer.prototype.begin = function () { + this.camera.update(); + this.enableRenderer(this.batcher); + }; + SceneRenderer.prototype.drawSkeleton = function (skeleton, premultipliedAlpha, slotRangeStart, slotRangeEnd) { + if (premultipliedAlpha === void 0) { premultipliedAlpha = false; } + if (slotRangeStart === void 0) { slotRangeStart = -1; } + if (slotRangeEnd === void 0) { slotRangeEnd = -1; } + this.enableRenderer(this.batcher); + this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd); + }; + SceneRenderer.prototype.drawSkeletonDebug = function (skeleton, premultipliedAlpha, ignoredBones) { + if (premultipliedAlpha === void 0) { premultipliedAlpha = false; } + if (ignoredBones === void 0) { ignoredBones = null; } + this.enableRenderer(this.shapes); + this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones); + }; + SceneRenderer.prototype.drawTexture = function (texture, x, y, width, height, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.batcher); + if (color === null) + color = this.WHITE; + var quad = this.QUAD; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + this.batcher.draw(texture, quad, this.QUAD_TRIANGLES); + }; + SceneRenderer.prototype.drawTextureUV = function (texture, x, y, width, height, u, v, u2, v2, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.batcher); + if (color === null) + color = this.WHITE; + var quad = this.QUAD; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + this.batcher.draw(texture, quad, this.QUAD_TRIANGLES); + }; + SceneRenderer.prototype.drawTextureRotated = function (texture, x, y, width, height, pivotX, pivotY, angle, color, premultipliedAlpha) { + if (color === void 0) { color = null; } + if (premultipliedAlpha === void 0) { premultipliedAlpha = false; } + this.enableRenderer(this.batcher); + if (color === null) + color = this.WHITE; + var quad = this.QUAD; + var worldOriginX = x + pivotX; + var worldOriginY = y + pivotY; + var fx = -pivotX; + var fy = -pivotY; + var fx2 = width - pivotX; + var fy2 = height - pivotY; + var p1x = fx; + var p1y = fy; + var p2x = fx; + var p2y = fy2; + var p3x = fx2; + var p3y = fy2; + var p4x = fx2; + var p4y = fy; + var x1 = 0; + var y1 = 0; + var x2 = 0; + var y2 = 0; + var x3 = 0; + var y3 = 0; + var x4 = 0; + var y4 = 0; + if (angle != 0) { + var cos = spine.MathUtils.cosDeg(angle); + var sin = spine.MathUtils.sinDeg(angle); + x1 = cos * p1x - sin * p1y; + y1 = sin * p1x + cos * p1y; + x4 = cos * p2x - sin * p2y; + y4 = sin * p2x + cos * p2y; + x3 = cos * p3x - sin * p3y; + y3 = sin * p3x + cos * p3y; + x2 = x3 + (x1 - x4); + y2 = y3 + (y1 - y4); + } + else { + x1 = p1x; + y1 = p1y; + x4 = p2x; + y4 = p2y; + x3 = p3x; + y3 = p3y; + x2 = p4x; + y2 = p4y; + } + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + var i = 0; + quad[i++] = x1; + quad[i++] = y1; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x2; + quad[i++] = y2; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x3; + quad[i++] = y3; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x4; + quad[i++] = y4; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + this.batcher.draw(texture, quad, this.QUAD_TRIANGLES); + }; + SceneRenderer.prototype.drawRegion = function (region, x, y, width, height, color, premultipliedAlpha) { + if (color === void 0) { color = null; } + if (premultipliedAlpha === void 0) { premultipliedAlpha = false; } + this.enableRenderer(this.batcher); + if (color === null) + color = this.WHITE; + var quad = this.QUAD; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + this.batcher.draw(region.texture, quad, this.QUAD_TRIANGLES); + }; + SceneRenderer.prototype.line = function (x, y, x2, y2, color, color2) { + if (color === void 0) { color = null; } + if (color2 === void 0) { color2 = null; } + this.enableRenderer(this.shapes); + this.shapes.line(x, y, x2, y2, color); + }; + SceneRenderer.prototype.triangle = function (filled, x, y, x2, y2, x3, y3, color, color2, color3) { + if (color === void 0) { color = null; } + if (color2 === void 0) { color2 = null; } + if (color3 === void 0) { color3 = null; } + this.enableRenderer(this.shapes); + this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3); + }; + SceneRenderer.prototype.quad = function (filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + if (color === void 0) { color = null; } + if (color2 === void 0) { color2 = null; } + if (color3 === void 0) { color3 = null; } + if (color4 === void 0) { color4 = null; } + this.enableRenderer(this.shapes); + this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4); + }; + SceneRenderer.prototype.rect = function (filled, x, y, width, height, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.shapes); + this.shapes.rect(filled, x, y, width, height, color); + }; + SceneRenderer.prototype.rectLine = function (filled, x1, y1, x2, y2, width, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.shapes); + this.shapes.rectLine(filled, x1, y1, x2, y2, width, color); + }; + SceneRenderer.prototype.polygon = function (polygonVertices, offset, count, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.shapes); + this.shapes.polygon(polygonVertices, offset, count, color); + }; + SceneRenderer.prototype.circle = function (filled, x, y, radius, color, segments) { + if (color === void 0) { color = null; } + if (segments === void 0) { segments = 0; } + this.enableRenderer(this.shapes); + this.shapes.circle(filled, x, y, radius, color, segments); + }; + SceneRenderer.prototype.curve = function (x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + if (color === void 0) { color = null; } + this.enableRenderer(this.shapes); + this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color); + }; + SceneRenderer.prototype.end = function () { + if (this.activeRenderer === this.batcher) + this.batcher.end(); + else if (this.activeRenderer === this.shapes) + this.shapes.end(); + this.activeRenderer = null; + }; + SceneRenderer.prototype.resize = function (resizeMode) { + var canvas = this.canvas; + var w = canvas.clientWidth; + var h = canvas.clientHeight; + if (canvas.width != w || canvas.height != h) { + canvas.width = w; + canvas.height = h; + } + this.context.gl.viewport(0, 0, canvas.width, canvas.height); + if (resizeMode === ResizeMode.Stretch) { + } + else if (resizeMode === ResizeMode.Expand) { + this.camera.setViewport(w, h); + } + else if (resizeMode === ResizeMode.Fit) { + var sourceWidth = canvas.width, sourceHeight = canvas.height; + var targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight; + var targetRatio = targetHeight / targetWidth; + var sourceRatio = sourceHeight / sourceWidth; + var scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; + this.camera.viewportWidth = sourceWidth * scale; + this.camera.viewportHeight = sourceHeight * scale; + } + this.camera.update(); + }; + SceneRenderer.prototype.enableRenderer = function (renderer) { + if (this.activeRenderer === renderer) + return; + this.end(); + if (renderer instanceof webgl.PolygonBatcher) { + this.batcherShader.bind(); + this.batcherShader.setUniform4x4f(webgl.Shader.MVP_MATRIX, this.camera.projectionView.values); + this.batcherShader.setUniformi("u_texture", 0); + this.batcher.begin(this.batcherShader); + this.activeRenderer = this.batcher; + } + else if (renderer instanceof webgl.ShapeRenderer) { + this.shapesShader.bind(); + this.shapesShader.setUniform4x4f(webgl.Shader.MVP_MATRIX, this.camera.projectionView.values); + this.shapes.begin(this.shapesShader); + this.activeRenderer = this.shapes; + } + else { + this.activeRenderer = this.skeletonDebugRenderer; + } + }; + SceneRenderer.prototype.dispose = function () { + this.batcher.dispose(); + this.batcherShader.dispose(); + this.shapes.dispose(); + this.shapesShader.dispose(); + this.skeletonDebugRenderer.dispose(); + }; + return SceneRenderer; + }()); + webgl.SceneRenderer = SceneRenderer; + var ResizeMode; + (function (ResizeMode) { + ResizeMode[ResizeMode["Stretch"] = 0] = "Stretch"; + ResizeMode[ResizeMode["Expand"] = 1] = "Expand"; + ResizeMode[ResizeMode["Fit"] = 2] = "Fit"; + })(ResizeMode = webgl.ResizeMode || (webgl.ResizeMode = {})); + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var Shader = (function () { + function Shader(context, vertexShader, fragmentShader) { + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.vs = null; + this.fs = null; + this.program = null; + this.tmp2x2 = new Float32Array(2 * 2); + this.tmp3x3 = new Float32Array(3 * 3); + this.tmp4x4 = new Float32Array(4 * 4); + this.vsSource = vertexShader; + this.fsSource = fragmentShader; + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + this.context.addRestorable(this); + this.compile(); + } + Shader.prototype.getProgram = function () { return this.program; }; + Shader.prototype.getVertexShader = function () { return this.vertexShader; }; + Shader.prototype.getFragmentShader = function () { return this.fragmentShader; }; + Shader.prototype.getVertexShaderSource = function () { return this.vsSource; }; + Shader.prototype.getFragmentSource = function () { return this.fsSource; }; + Shader.prototype.compile = function () { + var gl = this.context.gl; + try { + this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); + this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); + this.program = this.compileProgram(this.vs, this.fs); + } + catch (e) { + this.dispose(); + throw e; + } + }; + Shader.prototype.compileShader = function (type, source) { + var gl = this.context.gl; + var shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + if (!gl.isContextLost()) + throw new Error(error); + } + return shader; + }; + Shader.prototype.compileProgram = function (vs, fs) { + var gl = this.context.gl; + var program = gl.createProgram(); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); + gl.deleteProgram(program); + if (!gl.isContextLost()) + throw new Error(error); + } + return program; + }; + Shader.prototype.restore = function () { + this.compile(); + }; + Shader.prototype.bind = function () { + this.context.gl.useProgram(this.program); + }; + Shader.prototype.unbind = function () { + this.context.gl.useProgram(null); + }; + Shader.prototype.setUniformi = function (uniform, value) { + this.context.gl.uniform1i(this.getUniformLocation(uniform), value); + }; + Shader.prototype.setUniformf = function (uniform, value) { + this.context.gl.uniform1f(this.getUniformLocation(uniform), value); + }; + Shader.prototype.setUniform2f = function (uniform, value, value2) { + this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); + }; + Shader.prototype.setUniform3f = function (uniform, value, value2, value3) { + this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); + }; + Shader.prototype.setUniform4f = function (uniform, value, value2, value3, value4) { + this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); + }; + Shader.prototype.setUniform2x2f = function (uniform, value) { + var gl = this.context.gl; + this.tmp2x2.set(value); + gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); + }; + Shader.prototype.setUniform3x3f = function (uniform, value) { + var gl = this.context.gl; + this.tmp3x3.set(value); + gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); + }; + Shader.prototype.setUniform4x4f = function (uniform, value) { + var gl = this.context.gl; + this.tmp4x4.set(value); + gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); + }; + Shader.prototype.getUniformLocation = function (uniform) { + var gl = this.context.gl; + var location = gl.getUniformLocation(this.program, uniform); + if (!location && !gl.isContextLost()) + throw new Error("Couldn't find location for uniform " + uniform); + return location; + }; + Shader.prototype.getAttributeLocation = function (attribute) { + var gl = this.context.gl; + var location = gl.getAttribLocation(this.program, attribute); + if (location == -1 && !gl.isContextLost()) + throw new Error("Couldn't find location for attribute " + attribute); + return location; + }; + Shader.prototype.dispose = function () { + this.context.removeRestorable(this); + var gl = this.context.gl; + if (this.vs) { + gl.deleteShader(this.vs); + this.vs = null; + } + if (this.fs) { + gl.deleteShader(this.fs); + this.fs = null; + } + if (this.program) { + gl.deleteProgram(this.program); + this.program = null; + } + }; + Shader.newColoredTextured = function (context) { + var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tattribute vec2 " + Shader.TEXCOORDS + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_color;\n\t\t\t\tvarying vec2 v_texCoords;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_color = " + Shader.COLOR + ";\n\t\t\t\t\tv_texCoords = " + Shader.TEXCOORDS + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t"; + var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n\t\t\t\t}\n\t\t\t"; + return new Shader(context, vs, fs); + }; + Shader.newTwoColoredTextured = function (context) { + var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR2 + ";\n\t\t\t\tattribute vec2 " + Shader.TEXCOORDS + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_light;\n\t\t\t\tvarying vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_light = " + Shader.COLOR + ";\n\t\t\t\t\tv_dark = " + Shader.COLOR2 + ";\n\t\t\t\t\tv_texCoords = " + Shader.TEXCOORDS + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t"; + var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_light;\n\t\t\t\tvarying LOWP vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\t\t\t\t\tgl_FragColor.a = texColor.a * v_light.a;\n\t\t\t\t\tgl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n\t\t\t\t}\n\t\t\t"; + return new Shader(context, vs, fs); + }; + Shader.newColored = function (context) { + var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_color = " + Shader.COLOR + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t"; + var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color;\n\t\t\t\t}\n\t\t\t"; + return new Shader(context, vs, fs); + }; + Shader.MVP_MATRIX = "u_projTrans"; + Shader.POSITION = "a_position"; + Shader.COLOR = "a_color"; + Shader.COLOR2 = "a_color2"; + Shader.TEXCOORDS = "a_texCoords"; + Shader.SAMPLER = "u_texture"; + return Shader; + }()); + webgl.Shader = Shader; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var ShapeRenderer = (function () { + function ShapeRenderer(context, maxVertices) { + if (maxVertices === void 0) { maxVertices = 10920; } + this.isDrawing = false; + this.shapeType = ShapeType.Filled; + this.color = new spine.Color(1, 1, 1, 1); + this.vertexIndex = 0; + this.tmp = new spine.Vector2(); + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + this.mesh = new webgl.Mesh(context, [new webgl.Position2Attribute(), new webgl.ColorAttribute()], maxVertices, 0); + this.srcBlend = this.context.gl.SRC_ALPHA; + this.dstBlend = this.context.gl.ONE_MINUS_SRC_ALPHA; + } + ShapeRenderer.prototype.begin = function (shader) { + if (this.isDrawing) + throw new Error("ShapeRenderer.begin() has already been called"); + this.shader = shader; + this.vertexIndex = 0; + this.isDrawing = true; + var gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFunc(this.srcBlend, this.dstBlend); + }; + ShapeRenderer.prototype.setBlendMode = function (srcBlend, dstBlend) { + var gl = this.context.gl; + this.srcBlend = srcBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + gl.blendFunc(this.srcBlend, this.dstBlend); + } + }; + ShapeRenderer.prototype.setColor = function (color) { + this.color.setFromColor(color); + }; + ShapeRenderer.prototype.setColorWith = function (r, g, b, a) { + this.color.set(r, g, b, a); + }; + ShapeRenderer.prototype.point = function (x, y, color) { + if (color === void 0) { color = null; } + this.check(ShapeType.Point, 1); + if (color === null) + color = this.color; + this.vertex(x, y, color); + }; + ShapeRenderer.prototype.line = function (x, y, x2, y2, color) { + if (color === void 0) { color = null; } + this.check(ShapeType.Line, 2); + var vertices = this.mesh.getVertices(); + var idx = this.vertexIndex; + if (color === null) + color = this.color; + this.vertex(x, y, color); + this.vertex(x2, y2, color); + }; + ShapeRenderer.prototype.triangle = function (filled, x, y, x2, y2, x3, y3, color, color2, color3) { + if (color === void 0) { color = null; } + if (color2 === void 0) { color2 = null; } + if (color3 === void 0) { color3 = null; } + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + var vertices = this.mesh.getVertices(); + var idx = this.vertexIndex; + if (color === null) + color = this.color; + if (color2 === null) + color2 = this.color; + if (color3 === null) + color3 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + } + else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color); + this.vertex(x3, y3, color2); + this.vertex(x3, y3, color); + this.vertex(x, y, color2); + } + }; + ShapeRenderer.prototype.quad = function (filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + if (color === void 0) { color = null; } + if (color2 === void 0) { color2 = null; } + if (color3 === void 0) { color3 = null; } + if (color4 === void 0) { color4 = null; } + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + var vertices = this.mesh.getVertices(); + var idx = this.vertexIndex; + if (color === null) + color = this.color; + if (color2 === null) + color2 = this.color; + if (color3 === null) + color3 = this.color; + if (color4 === null) + color4 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + }; + ShapeRenderer.prototype.rect = function (filled, x, y, width, height, color) { + if (color === void 0) { color = null; } + this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color); + }; + ShapeRenderer.prototype.rectLine = function (filled, x1, y1, x2, y2, width, color) { + if (color === void 0) { color = null; } + this.check(filled ? ShapeType.Filled : ShapeType.Line, 8); + if (color === null) + color = this.color; + var t = this.tmp.set(y2 - y1, x1 - x2); + t.normalize(); + width *= 0.5; + var tx = t.x * width; + var ty = t.y * width; + if (!filled) { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + else { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + }; + ShapeRenderer.prototype.x = function (x, y, size) { + this.line(x - size, y - size, x + size, y + size); + this.line(x - size, y + size, x + size, y - size); + }; + ShapeRenderer.prototype.polygon = function (polygonVertices, offset, count, color) { + if (color === void 0) { color = null; } + if (count < 3) + throw new Error("Polygon must contain at least 3 vertices"); + this.check(ShapeType.Line, count * 2); + if (color === null) + color = this.color; + var vertices = this.mesh.getVertices(); + var idx = this.vertexIndex; + offset <<= 1; + count <<= 1; + var firstX = polygonVertices[offset]; + var firstY = polygonVertices[offset + 1]; + var last = offset + count; + for (var i = offset, n = offset + count - 2; i < n; i += 2) { + var x1 = polygonVertices[i]; + var y1 = polygonVertices[i + 1]; + var x2 = 0; + var y2 = 0; + if (i + 2 >= last) { + x2 = firstX; + y2 = firstY; + } + else { + x2 = polygonVertices[i + 2]; + y2 = polygonVertices[i + 3]; + } + this.vertex(x1, y1, color); + this.vertex(x2, y2, color); + } + }; + ShapeRenderer.prototype.circle = function (filled, x, y, radius, color, segments) { + if (color === void 0) { color = null; } + if (segments === void 0) { segments = 0; } + if (segments === 0) + segments = Math.max(1, (6 * spine.MathUtils.cbrt(radius)) | 0); + if (segments <= 0) + throw new Error("segments must be > 0."); + if (color === null) + color = this.color; + var angle = 2 * spine.MathUtils.PI / segments; + var cos = Math.cos(angle); + var sin = Math.sin(angle); + var cx = radius, cy = 0; + if (!filled) { + this.check(ShapeType.Line, segments * 2 + 2); + for (var i = 0; i < segments; i++) { + this.vertex(x + cx, y + cy, color); + var temp_1 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp_1 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x + cx, y + cy, color); + } + else { + this.check(ShapeType.Filled, segments * 3 + 3); + segments--; + for (var i = 0; i < segments; i++) { + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + var temp_2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp_2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + } + var temp = cx; + cx = radius; + cy = 0; + this.vertex(x + cx, y + cy, color); + }; + ShapeRenderer.prototype.curve = function (x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + if (color === void 0) { color = null; } + this.check(ShapeType.Line, segments * 2 + 2); + if (color === null) + color = this.color; + var subdiv_step = 1 / segments; + var subdiv_step2 = subdiv_step * subdiv_step; + var subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + var pre1 = 3 * subdiv_step; + var pre2 = 3 * subdiv_step2; + var pre4 = 6 * subdiv_step2; + var pre5 = 6 * subdiv_step3; + var tmp1x = x1 - cx1 * 2 + cx2; + var tmp1y = y1 - cy1 * 2 + cy2; + var tmp2x = (cx1 - cx2) * 3 - x1 + x2; + var tmp2y = (cy1 - cy2) * 3 - y1 + y2; + var fx = x1; + var fy = y1; + var dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + var dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + var ddfx = tmp1x * pre4 + tmp2x * pre5; + var ddfy = tmp1y * pre4 + tmp2y * pre5; + var dddfx = tmp2x * pre5; + var dddfy = tmp2y * pre5; + while (segments-- > 0) { + this.vertex(fx, fy, color); + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + this.vertex(fx, fy, color); + } + this.vertex(fx, fy, color); + this.vertex(x2, y2, color); + }; + ShapeRenderer.prototype.vertex = function (x, y, color) { + var idx = this.vertexIndex; + var vertices = this.mesh.getVertices(); + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color.r; + vertices[idx++] = color.g; + vertices[idx++] = color.b; + vertices[idx++] = color.a; + this.vertexIndex = idx; + }; + ShapeRenderer.prototype.end = function () { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + this.flush(); + this.context.gl.disable(this.context.gl.BLEND); + this.isDrawing = false; + }; + ShapeRenderer.prototype.flush = function () { + if (this.vertexIndex == 0) + return; + this.mesh.setVerticesLength(this.vertexIndex); + this.mesh.draw(this.shader, this.shapeType); + this.vertexIndex = 0; + }; + ShapeRenderer.prototype.check = function (shapeType, numVertices) { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + if (this.shapeType == shapeType) { + if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) + this.flush(); + else + return; + } + else { + this.flush(); + this.shapeType = shapeType; + } + }; + ShapeRenderer.prototype.dispose = function () { + this.mesh.dispose(); + }; + return ShapeRenderer; + }()); + webgl.ShapeRenderer = ShapeRenderer; + var ShapeType; + (function (ShapeType) { + ShapeType[ShapeType["Point"] = 0] = "Point"; + ShapeType[ShapeType["Line"] = 1] = "Line"; + ShapeType[ShapeType["Filled"] = 4] = "Filled"; + })(ShapeType = webgl.ShapeType || (webgl.ShapeType = {})); + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var SkeletonDebugRenderer = (function () { + function SkeletonDebugRenderer(context) { + this.boneLineColor = new spine.Color(1, 0, 0, 1); + this.boneOriginColor = new spine.Color(0, 1, 0, 1); + this.attachmentLineColor = new spine.Color(0, 0, 1, 0.5); + this.triangleLineColor = new spine.Color(1, 0.64, 0, 0.5); + this.pathColor = new spine.Color().setFromString("FF7F00"); + this.clipColor = new spine.Color(0.8, 0, 0, 2); + this.aabbColor = new spine.Color(0, 1, 0, 0.5); + this.drawBones = true; + this.drawRegionAttachments = true; + this.drawBoundingBoxes = true; + this.drawMeshHull = true; + this.drawMeshTriangles = true; + this.drawPaths = true; + this.drawSkeletonXY = false; + this.drawClipping = true; + this.premultipliedAlpha = false; + this.scale = 1; + this.boneWidth = 2; + this.bounds = new spine.SkeletonBounds(); + this.temp = new Array(); + this.vertices = spine.Utils.newFloatArray(2 * 1024); + this.context = context instanceof webgl.ManagedWebGLRenderingContext ? context : new webgl.ManagedWebGLRenderingContext(context); + } + SkeletonDebugRenderer.prototype.draw = function (shapes, skeleton, ignoredBones) { + if (ignoredBones === void 0) { ignoredBones = null; } + var skeletonX = skeleton.x; + var skeletonY = skeleton.y; + var gl = this.context.gl; + var srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; + shapes.setBlendMode(srcFunc, gl.ONE_MINUS_SRC_ALPHA); + var bones = skeleton.bones; + if (this.drawBones) { + shapes.setColor(this.boneLineColor); + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + if (bone.parent == null) + continue; + var x = skeletonX + bone.data.length * bone.a + bone.worldX; + var y = skeletonY + bone.data.length * bone.c + bone.worldY; + shapes.rectLine(true, skeletonX + bone.worldX, skeletonY + bone.worldY, x, y, this.boneWidth * this.scale); + } + if (this.drawSkeletonXY) + shapes.x(skeletonX, skeletonY, 4 * this.scale); + } + if (this.drawRegionAttachments) { + shapes.setColor(this.attachmentLineColor); + var slots = skeleton.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + var attachment = slot.getAttachment(); + if (attachment instanceof spine.RegionAttachment) { + var regionAttachment = attachment; + var vertices = this.vertices; + regionAttachment.computeWorldVertices(slot.bone, vertices, 0, 2); + shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); + shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]); + shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]); + shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]); + } + } + } + if (this.drawMeshHull || this.drawMeshTriangles) { + var slots = skeleton.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (!slot.bone.active) + continue; + var attachment = slot.getAttachment(); + if (!(attachment instanceof spine.MeshAttachment)) + continue; + var mesh = attachment; + var vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2); + var triangles = mesh.triangles; + var hullLength = mesh.hullLength; + if (this.drawMeshTriangles) { + shapes.setColor(this.triangleLineColor); + for (var ii = 0, nn = triangles.length; ii < nn; ii += 3) { + var v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2; + shapes.triangle(false, vertices[v1], vertices[v1 + 1], vertices[v2], vertices[v2 + 1], vertices[v3], vertices[v3 + 1]); + } + } + if (this.drawMeshHull && hullLength > 0) { + shapes.setColor(this.attachmentLineColor); + hullLength = (hullLength >> 1) * 2; + var lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1]; + for (var ii = 0, nn = hullLength; ii < nn; ii += 2) { + var x = vertices[ii], y = vertices[ii + 1]; + shapes.line(x, y, lastX, lastY); + lastX = x; + lastY = y; + } + } + } + } + if (this.drawBoundingBoxes) { + var bounds = this.bounds; + bounds.update(skeleton, true); + shapes.setColor(this.aabbColor); + shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight()); + var polygons = bounds.polygons; + var boxes = bounds.boundingBoxes; + for (var i = 0, n = polygons.length; i < n; i++) { + var polygon = polygons[i]; + shapes.setColor(boxes[i].color); + shapes.polygon(polygon, 0, polygon.length); + } + } + if (this.drawPaths) { + var slots = skeleton.slots; + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (!slot.bone.active) + continue; + var attachment = slot.getAttachment(); + if (!(attachment instanceof spine.PathAttachment)) + continue; + var path = attachment; + var nn = path.worldVerticesLength; + var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0); + path.computeWorldVertices(slot, 0, nn, world, 0, 2); + var color = this.pathColor; + var x1 = world[2], y1 = world[3], x2 = 0, y2 = 0; + if (path.closed) { + shapes.setColor(color); + var cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1]; + x2 = world[nn - 4]; + y2 = world[nn - 3]; + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + } + nn -= 4; + for (var ii = 4; ii < nn; ii += 6) { + var cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3]; + x2 = world[ii + 4]; + y2 = world[ii + 5]; + shapes.setColor(color); + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + x1 = x2; + y1 = y2; + } + } + } + if (this.drawBones) { + shapes.setColor(this.boneOriginColor); + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8); + } + } + if (this.drawClipping) { + var slots = skeleton.slots; + shapes.setColor(this.clipColor); + for (var i = 0, n = slots.length; i < n; i++) { + var slot = slots[i]; + if (!slot.bone.active) + continue; + var attachment = slot.getAttachment(); + if (!(attachment instanceof spine.ClippingAttachment)) + continue; + var clip = attachment; + var nn = clip.worldVerticesLength; + var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0); + clip.computeWorldVertices(slot, 0, nn, world, 0, 2); + for (var i_21 = 0, n_3 = world.length; i_21 < n_3; i_21 += 2) { + var x = world[i_21]; + var y = world[i_21 + 1]; + var x2 = world[(i_21 + 2) % world.length]; + var y2 = world[(i_21 + 3) % world.length]; + shapes.line(x, y, x2, y2); + } + } + } + }; + SkeletonDebugRenderer.prototype.dispose = function () { + }; + SkeletonDebugRenderer.LIGHT_GRAY = new spine.Color(192 / 255, 192 / 255, 192 / 255, 1); + SkeletonDebugRenderer.GREEN = new spine.Color(0, 1, 0, 1); + return SkeletonDebugRenderer; + }()); + webgl.SkeletonDebugRenderer = SkeletonDebugRenderer; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var Renderable = (function () { + function Renderable(vertices, numVertices, numFloats) { + this.vertices = vertices; + this.numVertices = numVertices; + this.numFloats = numFloats; + } + return Renderable; + }()); + ; + var SkeletonRenderer = (function () { + function SkeletonRenderer(context, twoColorTint) { + if (twoColorTint === void 0) { twoColorTint = true; } + this.premultipliedAlpha = false; + this.vertexEffect = null; + this.tempColor = new spine.Color(); + this.tempColor2 = new spine.Color(); + this.vertexSize = 2 + 2 + 4; + this.twoColorTint = false; + this.renderable = new Renderable(null, 0, 0); + this.clipper = new spine.SkeletonClipping(); + this.temp = new spine.Vector2(); + this.temp2 = new spine.Vector2(); + this.temp3 = new spine.Color(); + this.temp4 = new spine.Color(); + this.twoColorTint = twoColorTint; + if (twoColorTint) + this.vertexSize += 4; + this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024); + } + SkeletonRenderer.prototype.draw = function (batcher, skeleton, slotRangeStart, slotRangeEnd) { + if (slotRangeStart === void 0) { slotRangeStart = -1; } + if (slotRangeEnd === void 0) { slotRangeEnd = -1; } + var clipper = this.clipper; + var premultipliedAlpha = this.premultipliedAlpha; + var twoColorTint = this.twoColorTint; + var blendMode = null; + var tempPos = this.temp; + var tempUv = this.temp2; + var tempLight = this.temp3; + var tempDark = this.temp4; + var renderable = this.renderable; + var uvs = null; + var triangles = null; + var drawOrder = skeleton.drawOrder; + var attachmentColor = null; + var skeletonColor = skeleton.color; + var vertexSize = twoColorTint ? 12 : 8; + var inRange = false; + if (slotRangeStart == -1) + inRange = true; + for (var i = 0, n = drawOrder.length; i < n; i++) { + var clippedVertexSize = clipper.isClipping() ? 2 : vertexSize; + var slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) { + inRange = true; + } + if (!inRange) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) { + inRange = false; + } + var attachment = slot.getAttachment(); + var texture = null; + if (attachment instanceof spine.RegionAttachment) { + var region = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = 4; + renderable.numFloats = clippedVertexSize << 2; + region.computeWorldVertices(slot.bone, renderable.vertices, 0, clippedVertexSize); + triangles = SkeletonRenderer.QUAD_TRIANGLES; + uvs = region.uvs; + texture = region.region.renderObject.texture; + attachmentColor = region.color; + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = (mesh.worldVerticesLength >> 1); + renderable.numFloats = renderable.numVertices * clippedVertexSize; + if (renderable.numFloats > renderable.vertices.length) { + renderable.vertices = this.vertices = spine.Utils.newFloatArray(renderable.numFloats); + } + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize); + triangles = mesh.triangles; + texture = mesh.region.renderObject.texture; + uvs = mesh.uvs; + attachmentColor = mesh.color; + } + else if (attachment instanceof spine.ClippingAttachment) { + var clip = (attachment); + clipper.clipStart(slot, clip); + continue; + } + else { + clipper.clipEndWithSlot(slot); + continue; + } + if (texture != null) { + var slotColor = slot.color; + var finalColor = this.tempColor; + finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r; + finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g; + finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b; + finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; + if (premultipliedAlpha) { + finalColor.r *= finalColor.a; + finalColor.g *= finalColor.a; + finalColor.b *= finalColor.a; + } + var darkColor = this.tempColor2; + if (slot.darkColor == null) + darkColor.set(0, 0, 0, 1.0); + else { + if (premultipliedAlpha) { + darkColor.r = slot.darkColor.r * finalColor.a; + darkColor.g = slot.darkColor.g * finalColor.a; + darkColor.b = slot.darkColor.b * finalColor.a; + } + else { + darkColor.setFromColor(slot.darkColor); + } + darkColor.a = premultipliedAlpha ? 1.0 : 0.0; + } + var slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + batcher.setBlendMode(webgl.WebGLBlendModeConverter.getSourceGLBlendMode(blendMode, premultipliedAlpha), webgl.WebGLBlendModeConverter.getDestGLBlendMode(blendMode)); + } + if (clipper.isClipping()) { + clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint); + var clippedVertices = new Float32Array(clipper.clippedVertices); + var clippedTriangles = clipper.clippedTriangles; + if (this.vertexEffect != null) { + var vertexEffect = this.vertexEffect; + var verts = clippedVertices; + if (!twoColorTint) { + for (var v = 0, n_4 = clippedVertices.length; v < n_4; v += vertexSize) { + tempPos.x = verts[v]; + tempPos.y = verts[v + 1]; + tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]); + tempUv.x = verts[v + 6]; + tempUv.y = verts[v + 7]; + tempDark.set(0, 0, 0, 0); + vertexEffect.transform(tempPos, tempUv, tempLight, tempDark); + verts[v] = tempPos.x; + verts[v + 1] = tempPos.y; + verts[v + 2] = tempLight.r; + verts[v + 3] = tempLight.g; + verts[v + 4] = tempLight.b; + verts[v + 5] = tempLight.a; + verts[v + 6] = tempUv.x; + verts[v + 7] = tempUv.y; + } + } + else { + for (var v = 0, n_5 = clippedVertices.length; v < n_5; v += vertexSize) { + tempPos.x = verts[v]; + tempPos.y = verts[v + 1]; + tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]); + tempUv.x = verts[v + 6]; + tempUv.y = verts[v + 7]; + tempDark.set(verts[v + 8], verts[v + 9], verts[v + 10], verts[v + 11]); + vertexEffect.transform(tempPos, tempUv, tempLight, tempDark); + verts[v] = tempPos.x; + verts[v + 1] = tempPos.y; + verts[v + 2] = tempLight.r; + verts[v + 3] = tempLight.g; + verts[v + 4] = tempLight.b; + verts[v + 5] = tempLight.a; + verts[v + 6] = tempUv.x; + verts[v + 7] = tempUv.y; + verts[v + 8] = tempDark.r; + verts[v + 9] = tempDark.g; + verts[v + 10] = tempDark.b; + verts[v + 11] = tempDark.a; + } + } + } + batcher.draw(texture, clippedVertices, clippedTriangles); + } + else { + var verts = renderable.vertices; + if (this.vertexEffect != null) { + var vertexEffect = this.vertexEffect; + if (!twoColorTint) { + for (var v = 0, u = 0, n_6 = renderable.numFloats; v < n_6; v += vertexSize, u += 2) { + tempPos.x = verts[v]; + tempPos.y = verts[v + 1]; + tempUv.x = uvs[u]; + tempUv.y = uvs[u + 1]; + tempLight.setFromColor(finalColor); + tempDark.set(0, 0, 0, 0); + vertexEffect.transform(tempPos, tempUv, tempLight, tempDark); + verts[v] = tempPos.x; + verts[v + 1] = tempPos.y; + verts[v + 2] = tempLight.r; + verts[v + 3] = tempLight.g; + verts[v + 4] = tempLight.b; + verts[v + 5] = tempLight.a; + verts[v + 6] = tempUv.x; + verts[v + 7] = tempUv.y; + } + } + else { + for (var v = 0, u = 0, n_7 = renderable.numFloats; v < n_7; v += vertexSize, u += 2) { + tempPos.x = verts[v]; + tempPos.y = verts[v + 1]; + tempUv.x = uvs[u]; + tempUv.y = uvs[u + 1]; + tempLight.setFromColor(finalColor); + tempDark.setFromColor(darkColor); + vertexEffect.transform(tempPos, tempUv, tempLight, tempDark); + verts[v] = tempPos.x; + verts[v + 1] = tempPos.y; + verts[v + 2] = tempLight.r; + verts[v + 3] = tempLight.g; + verts[v + 4] = tempLight.b; + verts[v + 5] = tempLight.a; + verts[v + 6] = tempUv.x; + verts[v + 7] = tempUv.y; + verts[v + 8] = tempDark.r; + verts[v + 9] = tempDark.g; + verts[v + 10] = tempDark.b; + verts[v + 11] = tempDark.a; + } + } + } + else { + if (!twoColorTint) { + for (var v = 2, u = 0, n_8 = renderable.numFloats; v < n_8; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + } + } + else { + for (var v = 2, u = 0, n_9 = renderable.numFloats; v < n_9; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + verts[v + 6] = darkColor.r; + verts[v + 7] = darkColor.g; + verts[v + 8] = darkColor.b; + verts[v + 9] = darkColor.a; + } + } + } + var view = renderable.vertices.subarray(0, renderable.numFloats); + batcher.draw(texture, view, triangles); + } + } + clipper.clipEndWithSlot(slot); + } + clipper.clipEnd(); + }; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + return SkeletonRenderer; + }()); + webgl.SkeletonRenderer = SkeletonRenderer; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var Vector3 = (function () { + function Vector3(x, y, z) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + if (z === void 0) { z = 0; } + this.x = 0; + this.y = 0; + this.z = 0; + this.x = x; + this.y = y; + this.z = z; + } + Vector3.prototype.setFrom = function (v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + }; + Vector3.prototype.set = function (x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + }; + Vector3.prototype.add = function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + }; + Vector3.prototype.sub = function (v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + }; + Vector3.prototype.scale = function (s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + }; + Vector3.prototype.normalize = function () { + var len = this.length(); + if (len == 0) + return this; + len = 1 / len; + this.x *= len; + this.y *= len; + this.z *= len; + return this; + }; + Vector3.prototype.cross = function (v) { + return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + }; + Vector3.prototype.multiply = function (matrix) { + var l_mat = matrix.values; + return this.set(this.x * l_mat[webgl.M00] + this.y * l_mat[webgl.M01] + this.z * l_mat[webgl.M02] + l_mat[webgl.M03], this.x * l_mat[webgl.M10] + this.y * l_mat[webgl.M11] + this.z * l_mat[webgl.M12] + l_mat[webgl.M13], this.x * l_mat[webgl.M20] + this.y * l_mat[webgl.M21] + this.z * l_mat[webgl.M22] + l_mat[webgl.M23]); + }; + Vector3.prototype.project = function (matrix) { + var l_mat = matrix.values; + var l_w = 1 / (this.x * l_mat[webgl.M30] + this.y * l_mat[webgl.M31] + this.z * l_mat[webgl.M32] + l_mat[webgl.M33]); + return this.set((this.x * l_mat[webgl.M00] + this.y * l_mat[webgl.M01] + this.z * l_mat[webgl.M02] + l_mat[webgl.M03]) * l_w, (this.x * l_mat[webgl.M10] + this.y * l_mat[webgl.M11] + this.z * l_mat[webgl.M12] + l_mat[webgl.M13]) * l_w, (this.x * l_mat[webgl.M20] + this.y * l_mat[webgl.M21] + this.z * l_mat[webgl.M22] + l_mat[webgl.M23]) * l_w); + }; + Vector3.prototype.dot = function (v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + }; + Vector3.prototype.length = function () { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + }; + Vector3.prototype.distance = function (v) { + var a = v.x - this.x; + var b = v.y - this.y; + var c = v.z - this.z; + return Math.sqrt(a * a + b * b + c * c); + }; + return Vector3; + }()); + webgl.Vector3 = Vector3; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var webgl; + (function (webgl) { + var ManagedWebGLRenderingContext = (function () { + function ManagedWebGLRenderingContext(canvasOrContext, contextConfig) { + if (contextConfig === void 0) { contextConfig = { alpha: "true" }; } + this.restorables = new Array(); + if (!((canvasOrContext instanceof WebGLRenderingContext) || (canvasOrContext instanceof WebGL2RenderingContext))) { + this.setupCanvas(canvasOrContext, contextConfig); + } + else { + this.gl = canvasOrContext; + this.canvas = this.gl.canvas; + } + } + ManagedWebGLRenderingContext.prototype.setupCanvas = function (canvas, contextConfig) { + var _this = this; + this.gl = (canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig)); + this.canvas = canvas; + canvas.addEventListener("webglcontextlost", function (e) { + var event = e; + if (e) { + e.preventDefault(); + } + }); + canvas.addEventListener("webglcontextrestored", function (e) { + for (var i = 0, n = _this.restorables.length; i < n; i++) { + _this.restorables[i].restore(); + } + }); + }; + ManagedWebGLRenderingContext.prototype.addRestorable = function (restorable) { + this.restorables.push(restorable); + }; + ManagedWebGLRenderingContext.prototype.removeRestorable = function (restorable) { + var index = this.restorables.indexOf(restorable); + if (index > -1) + this.restorables.splice(index, 1); + }; + return ManagedWebGLRenderingContext; + }()); + webgl.ManagedWebGLRenderingContext = ManagedWebGLRenderingContext; + var WebGLBlendModeConverter = (function () { + function WebGLBlendModeConverter() { + } + WebGLBlendModeConverter.getDestGLBlendMode = function (blendMode) { + switch (blendMode) { + case spine.BlendMode.Normal: return WebGLBlendModeConverter.ONE_MINUS_SRC_ALPHA; + case spine.BlendMode.Additive: return WebGLBlendModeConverter.ONE; + case spine.BlendMode.Multiply: return WebGLBlendModeConverter.ONE_MINUS_SRC_ALPHA; + case spine.BlendMode.Screen: return WebGLBlendModeConverter.ONE_MINUS_SRC_ALPHA; + default: throw new Error("Unknown blend mode: " + blendMode); + } + }; + WebGLBlendModeConverter.getSourceGLBlendMode = function (blendMode, premultipliedAlpha) { + if (premultipliedAlpha === void 0) { premultipliedAlpha = false; } + switch (blendMode) { + case spine.BlendMode.Normal: return premultipliedAlpha ? WebGLBlendModeConverter.ONE : WebGLBlendModeConverter.SRC_ALPHA; + case spine.BlendMode.Additive: return premultipliedAlpha ? WebGLBlendModeConverter.ONE : WebGLBlendModeConverter.SRC_ALPHA; + case spine.BlendMode.Multiply: return WebGLBlendModeConverter.DST_COLOR; + case spine.BlendMode.Screen: return WebGLBlendModeConverter.ONE; + default: throw new Error("Unknown blend mode: " + blendMode); + } + }; + WebGLBlendModeConverter.ZERO = 0; + WebGLBlendModeConverter.ONE = 1; + WebGLBlendModeConverter.SRC_COLOR = 0x0300; + WebGLBlendModeConverter.ONE_MINUS_SRC_COLOR = 0x0301; + WebGLBlendModeConverter.SRC_ALPHA = 0x0302; + WebGLBlendModeConverter.ONE_MINUS_SRC_ALPHA = 0x0303; + WebGLBlendModeConverter.DST_ALPHA = 0x0304; + WebGLBlendModeConverter.ONE_MINUS_DST_ALPHA = 0x0305; + WebGLBlendModeConverter.DST_COLOR = 0x0306; + return WebGLBlendModeConverter; + }()); + webgl.WebGLBlendModeConverter = WebGLBlendModeConverter; + })(webgl = spine.webgl || (spine.webgl = {})); +})(spine || (spine = {})); +//# sourceMappingURL=spine-webgl.js.map \ No newline at end of file diff --git a/Spine插件/Spine_动画播放器_2.0/spine-webgl-4.2.js b/Spine插件/Spine_动画播放器_2.0/spine-webgl-4.2.js new file mode 100644 index 0000000..2eecdd4 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/spine-webgl-4.2.js @@ -0,0 +1,14152 @@ +"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-webgl/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, + CameraController: () => CameraController, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + Color2Attribute: () => Color2Attribute, + ColorAttribute: () => ColorAttribute, + 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, + GLTexture: () => GLTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + Inherit: () => Inherit, + InheritTimeline: () => InheritTimeline, + Input: () => Input, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + LoadingScreen: () => LoadingScreen, + M00: () => M00, + M01: () => M01, + M02: () => M02, + M03: () => M03, + M10: () => M10, + M11: () => M11, + M12: () => M12, + M13: () => M13, + M20: () => M20, + M21: () => M21, + M22: () => M22, + M23: () => M23, + M30: () => M30, + M31: () => M31, + M32: () => M32, + M33: () => M33, + ManagedWebGLRenderingContext: () => ManagedWebGLRenderingContext, + MathUtils: () => MathUtils, + Matrix4: () => Matrix42, + Mesh: () => Mesh, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + OrthoCamera: () => OrthoCamera, + 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, + PolygonBatcher: () => PolygonBatcher, + Pool: () => Pool, + Position2Attribute: () => Position2Attribute, + Position3Attribute: () => Position3Attribute, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + ResizeMode: () => ResizeMode, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + SceneRenderer: () => SceneRenderer, + SequenceTimeline: () => SequenceTimeline, + Shader: () => Shader, + ShapeRenderer: () => ShapeRenderer, + ShapeType: () => ShapeType, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonDebugRenderer: () => SkeletonDebugRenderer, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + SpineCanvas: () => SpineCanvas, + StringSet: () => StringSet, + TexCoordAttribute: () => TexCoordAttribute, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + Touch: () => Touch, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + Vector3: () => Vector3, + VertexAttachment: () => VertexAttachment, + VertexAttribute: () => VertexAttribute, + VertexAttributeType: () => VertexAttributeType, + 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, 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; + } + } + } + /** 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; + 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 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__ */ ((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__ */ ((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, worldVertices, offset, stride) { + if (this.sequence != null) this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices, 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, worldVertices, 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]; + 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, 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; + 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; + 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.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-webgl/src/WebGL.ts + var ManagedWebGLRenderingContext = class { + canvas; + gl; + restorables = []; + constructor(canvasOrContext, contextConfig = { alpha: true }) { + if (!(canvasOrContext instanceof WebGLRenderingContext || typeof WebGL2RenderingContext !== "undefined" && canvasOrContext instanceof WebGL2RenderingContext)) { + const canvas = canvasOrContext; + this.gl = canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig); + this.canvas = canvas; + canvas.addEventListener("webglcontextlost", this.contextLostHandler); + canvas.addEventListener("webglcontextrestored", this.contextRestoredHandler); + } else { + this.gl = canvasOrContext; + this.canvas = this.gl.canvas; + } + } + contextLostHandler = (e) => { + if (e) e.preventDefault(); + }; + contextRestoredHandler = () => { + for (let i = 0, n = this.restorables.length; i < n; i++) + this.restorables[i].restore(); + }; + dispose() { + this.canvas.removeEventListener("webglcontextlost", this.contextLostHandler); + this.canvas.removeEventListener("webglcontextrestored", this.contextRestoredHandler); + } + addRestorable(restorable) { + this.restorables.push(restorable); + } + removeRestorable(restorable) { + const index = this.restorables.indexOf(restorable); + if (index > -1) this.restorables.splice(index, 1); + } + }; + + // spine-webgl/src/GLTexture.ts + var GLTexture = class _GLTexture extends Texture { + context; + texture = null; + boundUnit = 0; + useMipMaps = false; + static DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false; + constructor(context, image, useMipMaps = false) { + super(image); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.useMipMaps = useMipMaps; + this.restore(); + this.context.addRestorable(this); + } + setFilters(minFilter, magFilter) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, _GLTexture.validateMagFilter(magFilter)); + this.useMipMaps = _GLTexture.usesMipMaps(minFilter); + if (this.useMipMaps) gl.generateMipmap(gl.TEXTURE_2D); + } + static validateMagFilter(magFilter) { + switch (magFilter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return 9729 /* Linear */; + default: + return magFilter; + } + } + static usesMipMaps(filter) { + switch (filter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return true; + default: + return false; + } + } + setWraps(uWrap, vWrap) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap); + } + update(useMipMaps) { + let gl = this.context.gl; + if (!this.texture) this.texture = this.context.gl.createTexture(); + this.bind(); + if (_GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : 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); + if (useMipMaps) gl.generateMipmap(gl.TEXTURE_2D); + } + restore() { + this.texture = null; + this.update(this.useMipMaps); + } + bind(unit = 0) { + let gl = this.context.gl; + this.boundUnit = unit; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + } + unbind() { + let gl = this.context.gl; + gl.activeTexture(gl.TEXTURE0 + this.boundUnit); + gl.bindTexture(gl.TEXTURE_2D, null); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteTexture(this.texture); + } + }; + + // spine-webgl/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(context, pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new GLTexture(context, image); + }, pathPrefix, downloader); + } + }; + + // spine-webgl/src/Vector3.ts + var Vector3 = class { + x = 0; + y = 0; + z = 0; + constructor(x = 0, y = 0, z = 0) { + this.x = x; + this.y = y; + this.z = z; + } + setFrom(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + set(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + scale(s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + } + normalize() { + let len = this.length(); + if (len == 0) return this; + len = 1 / len; + this.x *= len; + this.y *= len; + this.z *= len; + return this; + } + cross(v) { + return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + } + multiply(matrix) { + let l_mat = matrix.values; + return this.set( + this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03], + this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13], + this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23] + ); + } + project(matrix) { + let l_mat = matrix.values; + let l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]); + return this.set( + (this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w, + (this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w, + (this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w + ); + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + distance(v) { + let a = v.x - this.x; + let b = v.y - this.y; + let c = v.z - this.z; + return Math.sqrt(a * a + b * b + c * c); + } + }; + + // spine-webgl/src/Matrix4.ts + var M00 = 0; + var M01 = 4; + var M02 = 8; + var M03 = 12; + var M10 = 1; + var M11 = 5; + var M12 = 9; + var M13 = 13; + var M20 = 2; + var M21 = 6; + var M22 = 10; + var M23 = 14; + var M30 = 3; + var M31 = 7; + var M32 = 11; + var M33 = 15; + var Matrix42 = class _Matrix4 { + temp = new Float32Array(16); + values = new Float32Array(16); + static xAxis = new Vector3(); + static yAxis = new Vector3(); + static zAxis = new Vector3(); + static tmpMatrix = new _Matrix4(); + constructor() { + let v = this.values; + v[M00] = 1; + v[M11] = 1; + v[M22] = 1; + v[M33] = 1; + } + set(values) { + this.values.set(values); + return this; + } + transpose() { + let t = this.temp; + let v = this.values; + t[M00] = v[M00]; + t[M01] = v[M10]; + t[M02] = v[M20]; + t[M03] = v[M30]; + t[M10] = v[M01]; + t[M11] = v[M11]; + t[M12] = v[M21]; + t[M13] = v[M31]; + t[M20] = v[M02]; + t[M21] = v[M12]; + t[M22] = v[M22]; + t[M23] = v[M32]; + t[M30] = v[M03]; + t[M31] = v[M13]; + t[M32] = v[M23]; + t[M33] = v[M33]; + return this.set(t); + } + identity() { + let v = this.values; + v[M00] = 1; + v[M01] = 0; + v[M02] = 0; + v[M03] = 0; + v[M10] = 0; + v[M11] = 1; + v[M12] = 0; + v[M13] = 0; + v[M20] = 0; + v[M21] = 0; + v[M22] = 1; + v[M23] = 0; + v[M30] = 0; + v[M31] = 0; + v[M32] = 0; + v[M33] = 1; + return this; + } + invert() { + let v = this.values; + let t = this.temp; + let l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + if (l_det == 0) throw new Error("non-invertible matrix"); + let inv_det = 1 / l_det; + t[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32] - v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33]; + t[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32] + v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33]; + t[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32] - v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33]; + t[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22] + v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23]; + t[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32] + v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33]; + t[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32] - v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33]; + t[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32] + v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33]; + t[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22] - v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23]; + t[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31] - v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33]; + t[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31] + v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33]; + t[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31] - v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33]; + t[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21] + v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23]; + t[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31] + v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32]; + t[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31] - v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32]; + t[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31] + v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32]; + t[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21] - v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22]; + v[M00] = t[M00] * inv_det; + v[M01] = t[M01] * inv_det; + v[M02] = t[M02] * inv_det; + v[M03] = t[M03] * inv_det; + v[M10] = t[M10] * inv_det; + v[M11] = t[M11] * inv_det; + v[M12] = t[M12] * inv_det; + v[M13] = t[M13] * inv_det; + v[M20] = t[M20] * inv_det; + v[M21] = t[M21] * inv_det; + v[M22] = t[M22] * inv_det; + v[M23] = t[M23] * inv_det; + v[M30] = t[M30] * inv_det; + v[M31] = t[M31] * inv_det; + v[M32] = t[M32] * inv_det; + v[M33] = t[M33] * inv_det; + return this; + } + determinant() { + let v = this.values; + return v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + } + translate(x, y, z) { + let v = this.values; + v[M03] += x; + v[M13] += y; + v[M23] += z; + return this; + } + copy() { + return new _Matrix4().set(this.values); + } + projection(near, far, fovy, aspectRatio) { + this.identity(); + let l_fd = 1 / Math.tan(fovy * (Math.PI / 180) / 2); + let l_a1 = (far + near) / (near - far); + let l_a2 = 2 * far * near / (near - far); + let v = this.values; + v[M00] = l_fd / aspectRatio; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = l_fd; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = l_a1; + v[M32] = -1; + v[M03] = 0; + v[M13] = 0; + v[M23] = l_a2; + v[M33] = 0; + return this; + } + ortho2d(x, y, width, height) { + return this.ortho(x, x + width, y, y + height, 0, 1); + } + ortho(left, right, bottom, top, near, far) { + this.identity(); + let x_orth = 2 / (right - left); + let y_orth = 2 / (top - bottom); + let z_orth = -2 / (far - near); + let tx = -(right + left) / (right - left); + let ty = -(top + bottom) / (top - bottom); + let tz = -(far + near) / (far - near); + let v = this.values; + v[M00] = x_orth; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = y_orth; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = z_orth; + v[M32] = 0; + v[M03] = tx; + v[M13] = ty; + v[M23] = tz; + v[M33] = 1; + return this; + } + multiply(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30]; + t[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31]; + t[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32]; + t[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33]; + t[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30]; + t[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31]; + t[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32]; + t[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33]; + t[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30]; + t[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31]; + t[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32]; + t[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33]; + t[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30]; + t[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31]; + t[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32]; + t[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33]; + return this.set(this.temp); + } + multiplyLeft(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30]; + t[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31]; + t[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32]; + t[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33]; + t[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30]; + t[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31]; + t[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32]; + t[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33]; + t[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30]; + t[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31]; + t[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32]; + t[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33]; + t[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30]; + t[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31]; + t[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32]; + t[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33]; + return this.set(this.temp); + } + lookAt(position, direction, up) { + let xAxis = _Matrix4.xAxis, yAxis = _Matrix4.yAxis, zAxis = _Matrix4.zAxis; + zAxis.setFrom(direction).normalize(); + xAxis.setFrom(direction).normalize(); + xAxis.cross(up).normalize(); + yAxis.setFrom(xAxis).cross(zAxis).normalize(); + this.identity(); + let val = this.values; + val[M00] = xAxis.x; + val[M01] = xAxis.y; + val[M02] = xAxis.z; + val[M10] = yAxis.x; + val[M11] = yAxis.y; + val[M12] = yAxis.z; + val[M20] = -zAxis.x; + val[M21] = -zAxis.y; + val[M22] = -zAxis.z; + _Matrix4.tmpMatrix.identity(); + _Matrix4.tmpMatrix.values[M03] = -position.x; + _Matrix4.tmpMatrix.values[M13] = -position.y; + _Matrix4.tmpMatrix.values[M23] = -position.z; + this.multiply(_Matrix4.tmpMatrix); + return this; + } + }; + + // spine-webgl/src/Camera.ts + var OrthoCamera = class { + position = new Vector3(0, 0, 0); + direction = new Vector3(0, 0, -1); + up = new Vector3(0, 1, 0); + near = 0; + far = 100; + zoom = 1; + viewportWidth = 0; + viewportHeight = 0; + projectionView = new Matrix42(); + inverseProjectionView = new Matrix42(); + projection = new Matrix42(); + view = new Matrix42(); + constructor(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.update(); + } + update() { + let projection = this.projection; + let view = this.view; + let projectionView = this.projectionView; + let inverseProjectionView = this.inverseProjectionView; + let zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight; + projection.ortho( + zoom * (-viewportWidth / 2), + zoom * (viewportWidth / 2), + zoom * (-viewportHeight / 2), + zoom * (viewportHeight / 2), + this.near, + this.far + ); + view.lookAt(this.position, this.direction, this.up); + projectionView.set(projection.values); + projectionView.multiply(view); + inverseProjectionView.set(projectionView.values).invert(); + } + screenToWorld(screenCoords, screenWidth, screenHeight) { + let x = screenCoords.x, y = screenHeight - screenCoords.y - 1; + screenCoords.x = 2 * x / screenWidth - 1; + screenCoords.y = 2 * y / screenHeight - 1; + screenCoords.z = 2 * screenCoords.z - 1; + screenCoords.project(this.inverseProjectionView); + return screenCoords; + } + worldToScreen(worldCoords, screenWidth, screenHeight) { + worldCoords.project(this.projectionView); + worldCoords.x = screenWidth * (worldCoords.x + 1) / 2; + worldCoords.y = screenHeight * (worldCoords.y + 1) / 2; + worldCoords.z = (worldCoords.z + 1) / 2; + return worldCoords; + } + setViewport(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + } + }; + + // spine-webgl/src/Input.ts + var Input = class { + element; + mouseX = 0; + mouseY = 0; + buttonDown = false; + touch0 = null; + touch1 = null; + initialPinchDistance = 0; + listeners = new Array(); + autoPreventDefault; + // this is needed because browsers sends mousedown-mousemove-mousesup after a touch sequence, unless touch end preventDefault + // but preventing default will result in preventing interaction with the page. + isTouch = false; + callbacks; + constructor(element, autoPreventDefault = true) { + this.element = element; + this.autoPreventDefault = autoPreventDefault; + this.callbacks = this.setupCallbacks(element); + } + setupCallbacks(element) { + const mouseDown = (ev) => { + if (ev instanceof MouseEvent && !this.isTouch) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) listener.down(this.mouseX, this.mouseY, ev); + }); + } + }; + const mouseMove = (ev) => { + if (ev instanceof MouseEvent && !this.isTouch) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + this.mouseY = ev.clientY - rect.top; + this.listeners.map((listener) => { + if (this.buttonDown) { + if (listener.dragged) listener.dragged(this.mouseX, this.mouseY, ev); + } else { + if (listener.moved) listener.moved(this.mouseX, this.mouseY, ev); + } + }); + } + }; + const mouseUp = (ev) => { + if (ev instanceof MouseEvent && !this.isTouch) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = false; + this.listeners.map((listener) => { + if (listener.up) listener.up(this.mouseX, this.mouseY, ev); + }); + } + }; + const mouseWheel = (ev) => { + if (this.autoPreventDefault) ev.preventDefault(); + let deltaY = ev.deltaY; + if (ev.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8; + if (ev.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24; + this.listeners.map((listener) => { + if (listener.wheel) listener.wheel(ev.deltaY, ev); + }); + }; + const touchStart = (ev) => { + this.isTouch = true; + if (!this.touch0 || !this.touch1) { + var touches = ev.changedTouches; + let nativeTouch = touches.item(0); + if (!nativeTouch) return; + let rect = element.getBoundingClientRect(); + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + let touch = new Touch(nativeTouch.identifier, x, y); + this.mouseX = x; + this.mouseY = y; + this.buttonDown = true; + if (!this.touch0) { + this.touch0 = touch; + this.listeners.map((listener) => { + if (listener.down) listener.down(touch.x, touch.y, ev); + }); + } else if (!this.touch1) { + this.touch1 = touch; + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance, ev); + }); + } + } + if (this.autoPreventDefault) ev.preventDefault(); + }; + const touchMove = (ev) => { + this.isTouch = true; + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0.x = this.mouseX = x; + this.touch0.y = this.mouseY = y; + this.listeners.map((listener) => { + if (listener.dragged) listener.dragged(x, y, ev); + }); + } + if (this.touch1 && this.touch1.identifier === nativeTouch.identifier) { + this.touch1.x = this.mouseX = x; + this.touch1.y = this.mouseY = y; + } + } + if (this.touch0 && this.touch1) { + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + let distance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) listener.zoom(this.initialPinchDistance, distance, ev); + }); + } + } + if (this.autoPreventDefault) ev.preventDefault(); + }; + const touchEnd = (ev) => { + this.isTouch = true; + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0 = null; + this.mouseX = x; + this.mouseY = y; + this.listeners.map((listener) => { + if (listener.up) listener.up(x, y, ev); + }); + if (!this.touch1) { + this.buttonDown = false; + break; + } else { + this.touch0 = this.touch1; + this.touch1 = null; + this.mouseX = this.touch0.x; + this.mouseX = this.touch0.x; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) listener.down(this.touch0.x, this.touch0.y, ev); + }); + } + } + if (this.touch1 && this.touch1.identifier) { + this.touch1 = null; + } + } + } + if (this.autoPreventDefault) ev.preventDefault(); + }; + element.addEventListener("mousedown", mouseDown, true); + element.addEventListener("mousemove", mouseMove, true); + element.addEventListener("mouseup", mouseUp, true); + element.addEventListener("wheel", mouseWheel, true); + element.addEventListener("touchstart", touchStart, { passive: false, capture: false }); + element.addEventListener("touchmove", touchMove, { passive: false, capture: false }); + element.addEventListener("touchend", touchEnd, { passive: false, capture: false }); + element.addEventListener("touchcancel", touchEnd); + return { + mouseDown, + mouseMove, + mouseUp, + mouseWheel, + touchStart, + touchMove, + touchEnd + }; + } + dispose() { + const element = this.element; + element.removeEventListener("mousedown", this.callbacks.mouseDown, true); + element.removeEventListener("mousemove", this.callbacks.mouseMove, true); + element.removeEventListener("mouseup", this.callbacks.mouseUp, true); + element.removeEventListener("wheel", this.callbacks.mouseWheel, true); + element.removeEventListener("touchstart", this.callbacks.touchStart, { capture: false }); + element.removeEventListener("touchmove", this.callbacks.touchMove, { capture: false }); + element.removeEventListener("touchend", this.callbacks.touchEnd, { capture: false }); + element.removeEventListener("touchcancel", this.callbacks.touchEnd); + this.listeners.length = 0; + } + addListener(listener) { + this.listeners.push(listener); + } + removeListener(listener) { + let idx = this.listeners.indexOf(listener); + if (idx > -1) { + this.listeners.splice(idx, 1); + } + } + }; + var Touch = class { + constructor(identifier, x, y) { + this.identifier = identifier; + this.x = x; + this.y = y; + } + }; + + // spine-webgl/src/CameraController.ts + var CameraController = class { + constructor(canvas, camera) { + this.canvas = canvas; + this.camera = camera; + let cameraX = 0, cameraY = 0, cameraZoom = 0; + let mouseX = 0, mouseY = 0; + let lastX = 0, lastY = 0; + let initialZoom = 0; + new Input(canvas).addListener({ + down: (x, y) => { + cameraX = camera.position.x; + cameraY = camera.position.y; + mouseX = lastX = x; + mouseY = lastY = y; + initialZoom = camera.zoom; + }, + dragged: (x, y) => { + let deltaX = x - mouseX; + let deltaY = y - mouseY; + let originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight); + let deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld); + camera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0); + camera.update(); + lastX = x; + lastY = y; + }, + wheel: (delta) => { + let zoomAmount = delta / 200 * camera.zoom; + let newZoom = camera.zoom + zoomAmount; + if (newZoom > 0) { + let x = 0, y = 0; + if (delta < 0) { + x = lastX; + y = lastY; + } else { + let viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2); + let mouseToCenterX = lastX - viewCenter.x; + let mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y; + x = viewCenter.x - mouseToCenterX; + y = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY; + } + let oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.zoom = newZoom; + camera.update(); + let newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.position.add(oldDistance.sub(newDistance)); + camera.update(); + } + }, + zoom: (initialDistance, distance) => { + let newZoom = initialDistance / distance; + camera.zoom = initialZoom * newZoom; + }, + up: (x, y) => { + lastX = x; + lastY = y; + }, + moved: (x, y) => { + lastX = x; + lastY = y; + } + }); + } + }; + + // spine-webgl/src/Shader.ts + var Shader = class _Shader { + constructor(context, vertexShader, fragmentShader) { + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.vsSource = vertexShader; + this.fsSource = fragmentShader; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.context.addRestorable(this); + this.compile(); + } + static MVP_MATRIX = "u_projTrans"; + static POSITION = "a_position"; + static COLOR = "a_color"; + static COLOR2 = "a_color2"; + static TEXCOORDS = "a_texCoords"; + static SAMPLER = "u_texture"; + context; + vs = null; + vsSource; + fs = null; + fsSource; + program = null; + tmp2x2 = new Float32Array(2 * 2); + tmp3x3 = new Float32Array(3 * 3); + tmp4x4 = new Float32Array(4 * 4); + getProgram() { + return this.program; + } + getVertexShader() { + return this.vertexShader; + } + getFragmentShader() { + return this.fragmentShader; + } + getVertexShaderSource() { + return this.vsSource; + } + getFragmentSource() { + return this.fsSource; + } + compile() { + let gl = this.context.gl; + try { + this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); + if (!this.vs) throw new Error("Couldn't compile vertex shader."); + this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); + if (!this.fs) throw new Error("Couldn#t compile fragment shader."); + this.program = this.compileProgram(this.vs, this.fs); + } catch (e) { + this.dispose(); + throw e; + } + } + compileShader(type, source) { + let gl = this.context.gl; + let shader = gl.createShader(type); + if (!shader) throw new Error("Couldn't create shader."); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + if (!gl.isContextLost()) throw new Error(error); + } + return shader; + } + compileProgram(vs, fs) { + let gl = this.context.gl; + let program = gl.createProgram(); + if (!program) throw new Error("Couldn't compile program."); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); + gl.deleteProgram(program); + if (!gl.isContextLost()) throw new Error(error); + } + return program; + } + restore() { + this.compile(); + } + bind() { + this.context.gl.useProgram(this.program); + } + unbind() { + this.context.gl.useProgram(null); + } + setUniformi(uniform, value) { + this.context.gl.uniform1i(this.getUniformLocation(uniform), value); + } + setUniformf(uniform, value) { + this.context.gl.uniform1f(this.getUniformLocation(uniform), value); + } + setUniform2f(uniform, value, value2) { + this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); + } + setUniform3f(uniform, value, value2, value3) { + this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); + } + setUniform4f(uniform, value, value2, value3, value4) { + this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); + } + setUniform2x2f(uniform, value) { + let gl = this.context.gl; + this.tmp2x2.set(value); + gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); + } + setUniform3x3f(uniform, value) { + let gl = this.context.gl; + this.tmp3x3.set(value); + gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); + } + setUniform4x4f(uniform, value) { + let gl = this.context.gl; + this.tmp4x4.set(value); + gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); + } + getUniformLocation(uniform) { + let gl = this.context.gl; + if (!this.program) throw new Error("Shader not compiled."); + let location = gl.getUniformLocation(this.program, uniform); + if (!location && !gl.isContextLost()) throw new Error(`Couldn't find location for uniform ${uniform}`); + return location; + } + getAttributeLocation(attribute) { + let gl = this.context.gl; + if (!this.program) throw new Error("Shader not compiled."); + let location = gl.getAttribLocation(this.program, attribute); + if (location == -1 && !gl.isContextLost()) throw new Error(`Couldn't find location for attribute ${attribute}`); + return location; + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + if (this.vs) { + gl.deleteShader(this.vs); + this.vs = null; + } + if (this.fs) { + gl.deleteShader(this.fs); + this.fs = null; + } + if (this.program) { + gl.deleteProgram(this.program); + this.program = null; + } + } + static newColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; +varying vec2 v_texCoords; + +void main () { + v_color = ${_Shader.COLOR}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + gl_FragColor = v_color * texture2D(u_texture, v_texCoords); +} +`; + return new _Shader(context, vs, fs); + } + static newTwoColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec4 ${_Shader.COLOR2}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_light; +varying vec4 v_dark; +varying vec2 v_texCoords; + +void main () { + v_light = ${_Shader.COLOR}; + v_dark = ${_Shader.COLOR2}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_light; +varying LOWP vec4 v_dark; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + vec4 texColor = texture2D(u_texture, v_texCoords); + gl_FragColor.a = texColor.a * v_light.a; + gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; +} +`; + return new _Shader(context, vs, fs); + } + static newColored(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; + +void main () { + v_color = ${_Shader.COLOR}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; + +void main () { + gl_FragColor = v_color; +} +`; + return new _Shader(context, vs, fs); + } + }; + + // spine-webgl/src/Mesh.ts + var Mesh = class { + constructor(context, attributes, maxVertices, maxIndices) { + this.attributes = attributes; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.elementsPerVertex = 0; + for (let i = 0; i < attributes.length; i++) { + this.elementsPerVertex += attributes[i].numElements; + } + this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); + this.indices = new Uint16Array(maxIndices); + this.context.addRestorable(this); + } + context; + vertices; + verticesBuffer = null; + verticesLength = 0; + dirtyVertices = false; + indices; + indicesBuffer = null; + indicesLength = 0; + dirtyIndices = false; + elementsPerVertex = 0; + getAttributes() { + return this.attributes; + } + maxVertices() { + return this.vertices.length / this.elementsPerVertex; + } + numVertices() { + return this.verticesLength / this.elementsPerVertex; + } + setVerticesLength(length) { + this.dirtyVertices = true; + this.verticesLength = length; + } + getVertices() { + return this.vertices; + } + maxIndices() { + return this.indices.length; + } + numIndices() { + return this.indicesLength; + } + setIndicesLength(length) { + this.dirtyIndices = true; + this.indicesLength = length; + } + getIndices() { + return this.indices; + } + getVertexSizeInFloats() { + let size = 0; + for (var i = 0; i < this.attributes.length; i++) { + let attribute = this.attributes[i]; + size += attribute.numElements; + } + return size; + } + setVertices(vertices) { + this.dirtyVertices = true; + if (vertices.length > this.vertices.length) throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); + this.vertices.set(vertices, 0); + this.verticesLength = vertices.length; + } + setIndices(indices) { + this.dirtyIndices = true; + if (indices.length > this.indices.length) throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); + this.indices.set(indices, 0); + this.indicesLength = indices.length; + } + draw(shader, primitiveType) { + this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); + } + drawWithOffset(shader, primitiveType, offset, count) { + let gl = this.context.gl; + if (this.dirtyVertices || this.dirtyIndices) this.update(); + this.bind(shader); + if (this.indicesLength > 0) { + gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); + } else { + gl.drawArrays(primitiveType, offset, count); + } + this.unbind(shader); + } + bind(shader) { + let gl = this.context.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + let offset = 0; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); + offset += attrib.numElements; + } + if (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + } + unbind(shader) { + let gl = this.context.gl; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.disableVertexAttribArray(location); + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + if (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + } + update() { + let gl = this.context.gl; + if (this.dirtyVertices) { + if (!this.verticesBuffer) { + this.verticesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); + this.dirtyVertices = false; + } + if (this.dirtyIndices) { + if (!this.indicesBuffer) { + this.indicesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); + this.dirtyIndices = false; + } + } + restore() { + this.verticesBuffer = null; + this.indicesBuffer = null; + this.update(); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteBuffer(this.verticesBuffer); + gl.deleteBuffer(this.indicesBuffer); + } + }; + var VertexAttribute = class { + constructor(name, type, numElements) { + this.name = name; + this.type = type; + this.numElements = numElements; + } + }; + var Position2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, 0 /* Float */, 2); + } + }; + var Position3Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, 0 /* Float */, 3); + } + }; + var TexCoordAttribute = class extends VertexAttribute { + constructor(unit = 0) { + super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), 0 /* Float */, 2); + } + }; + var ColorAttribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR, 0 /* Float */, 4); + } + }; + var Color2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR2, 0 /* Float */, 4); + } + }; + var VertexAttributeType = /* @__PURE__ */ ((VertexAttributeType2) => { + VertexAttributeType2[VertexAttributeType2["Float"] = 0] = "Float"; + return VertexAttributeType2; + })(VertexAttributeType || {}); + + // spine-webgl/src/PolygonBatcher.ts + var GL_ONE = 1; + var GL_ONE_MINUS_SRC_COLOR = 769; + var GL_SRC_ALPHA = 770; + var GL_ONE_MINUS_SRC_ALPHA = 771; + var GL_DST_COLOR = 774; + var PolygonBatcher = class _PolygonBatcher { + static disableCulling = false; + context; + drawCalls = 0; + static globalDrawCalls = 0; + isDrawing = false; + mesh; + shader = null; + lastTexture = null; + verticesLength = 0; + indicesLength = 0; + srcColorBlend; + srcAlphaBlend; + dstBlend; + cullWasEnabled = false; + constructor(context, twoColorTint = true, maxVertices = 10920) { + if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + let attributes = twoColorTint ? [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] : [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()]; + this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()"); + this.drawCalls = 0; + this.shader = shader; + this.lastTexture = null; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + if (_PolygonBatcher.disableCulling) { + this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE); + if (this.cullWasEnabled) gl.disable(gl.CULL_FACE); + } + } + static blendModesGL = [ + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE }, + { srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE } + ]; + setBlendMode(blendMode, premultipliedAlpha) { + const blendModeGL = _PolygonBatcher.blendModesGL[blendMode]; + const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb; + const srcAlphaBlend = blendModeGL.srcAlpha; + const dstBlend = blendModeGL.dstRgb; + if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return; + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + } + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + draw(texture, vertices, indices) { + if (texture != this.lastTexture) { + this.flush(); + this.lastTexture = texture; + } else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || this.indicesLength + indices.length > this.mesh.getIndices().length) { + this.flush(); + } + let indexStart = this.mesh.numVertices(); + this.mesh.getVertices().set(vertices, this.verticesLength); + this.verticesLength += vertices.length; + this.mesh.setVerticesLength(this.verticesLength); + let indicesArray = this.mesh.getIndices(); + for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++) + indicesArray[i] = indices[j] + indexStart; + this.indicesLength += indices.length; + this.mesh.setIndicesLength(this.indicesLength); + } + flush() { + if (this.verticesLength == 0) return; + if (!this.lastTexture) throw new Error("No texture set."); + if (!this.shader) throw new Error("No shader set."); + this.lastTexture.bind(); + this.mesh.draw(this.shader, this.context.gl.TRIANGLES); + this.verticesLength = 0; + this.indicesLength = 0; + this.mesh.setVerticesLength(0); + this.mesh.setIndicesLength(0); + this.drawCalls++; + _PolygonBatcher.globalDrawCalls++; + } + end() { + if (!this.isDrawing) throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()"); + if (this.verticesLength > 0 || this.indicesLength > 0) this.flush(); + this.shader = null; + this.lastTexture = null; + this.isDrawing = false; + let gl = this.context.gl; + gl.disable(gl.BLEND); + if (_PolygonBatcher.disableCulling) { + if (this.cullWasEnabled) gl.enable(gl.CULL_FACE); + } + } + getDrawCalls() { + return this.drawCalls; + } + static getAndResetGlobalDrawCalls() { + let result = _PolygonBatcher.globalDrawCalls; + _PolygonBatcher.globalDrawCalls = 0; + return result; + } + dispose() { + this.mesh.dispose(); + } + }; + + // spine-webgl/src/ShapeRenderer.ts + var ShapeRenderer = class { + context; + isDrawing = false; + mesh; + shapeType = 4 /* Filled */; + color = new Color(1, 1, 1, 1); + shader = null; + vertexIndex = 0; + tmp = new Vector2(); + srcColorBlend; + srcAlphaBlend; + dstBlend; + constructor(context, maxVertices = 10920) { + if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) throw new Error("ShapeRenderer.begin() has already been called"); + this.shader = shader; + this.vertexIndex = 0; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + } + setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) { + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + } + setColor(color) { + this.color.setFromColor(color); + } + setColorWith(r, g, b, a) { + this.color.set(r, g, b, a); + } + point(x, y, color) { + this.check(0 /* Point */, 1); + if (!color) color = this.color; + this.vertex(x, y, color); + } + line(x, y, x2, y2, color) { + this.check(1 /* Line */, 2); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) color = this.color; + this.vertex(x, y, color); + this.vertex(x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.check(filled ? 4 /* Filled */ : 1 /* Line */, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) color = this.color; + if (!color2) color2 = this.color; + if (!color3) color3 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color); + this.vertex(x3, y3, color2); + this.vertex(x3, y3, color); + this.vertex(x, y, color2); + } + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.check(filled ? 4 /* Filled */ : 1 /* Line */, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) color = this.color; + if (!color2) color2 = this.color; + if (!color3) color3 = this.color; + if (!color4) color4 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + } + rect(filled, x, y, width, height, color) { + this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.check(filled ? 4 /* Filled */ : 1 /* Line */, 8); + if (!color) color = this.color; + let t = this.tmp.set(y2 - y1, x1 - x2); + t.normalize(); + width *= 0.5; + let tx = t.x * width; + let ty = t.y * width; + if (!filled) { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } else { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + } + x(x, y, size) { + this.line(x - size, y - size, x + size, y + size); + this.line(x - size, y + size, x + size, y - size); + } + polygon(polygonVertices, offset, count, color) { + if (count < 3) throw new Error("Polygon must contain at least 3 vertices"); + this.check(1 /* Line */, count * 2); + if (!color) color = this.color; + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + offset <<= 1; + count <<= 1; + let firstX = polygonVertices[offset]; + let firstY = polygonVertices[offset + 1]; + let last = offset + count; + for (let i = offset, n = offset + count - 2; i < n; i += 2) { + let x1 = polygonVertices[i]; + let y1 = polygonVertices[i + 1]; + let x2 = 0; + let y2 = 0; + if (i + 2 >= last) { + x2 = firstX; + y2 = firstY; + } else { + x2 = polygonVertices[i + 2]; + y2 = polygonVertices[i + 3]; + } + this.vertex(x1, y1, color); + this.vertex(x2, y2, color); + } + } + circle(filled, x, y, radius, color, segments = 0) { + if (segments == 0) segments = Math.max(1, 6 * MathUtils.cbrt(radius) | 0); + if (segments <= 0) throw new Error("segments must be > 0."); + if (!color) color = this.color; + let angle = 2 * MathUtils.PI / segments; + let cos = Math.cos(angle); + let sin = Math.sin(angle); + let cx = radius, cy = 0; + if (!filled) { + this.check(1 /* Line */, segments * 2 + 2); + for (let i = 0; i < segments; i++) { + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x + cx, y + cy, color); + } else { + this.check(4 /* Filled */, segments * 3 + 3); + segments--; + for (let i = 0; i < segments; i++) { + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + } + let temp = cx; + cx = radius; + cy = 0; + this.vertex(x + cx, y + cy, color); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.check(1 /* Line */, segments * 2 + 2); + if (!color) color = this.color; + let subdiv_step = 1 / segments; + let subdiv_step2 = subdiv_step * subdiv_step; + let subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + let pre1 = 3 * subdiv_step; + let pre2 = 3 * subdiv_step2; + let pre4 = 6 * subdiv_step2; + let pre5 = 6 * subdiv_step3; + let tmp1x = x1 - cx1 * 2 + cx2; + let tmp1y = y1 - cy1 * 2 + cy2; + let tmp2x = (cx1 - cx2) * 3 - x1 + x2; + let tmp2y = (cy1 - cy2) * 3 - y1 + y2; + let fx = x1; + let fy = y1; + let dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + let dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + let ddfx = tmp1x * pre4 + tmp2x * pre5; + let ddfy = tmp1y * pre4 + tmp2y * pre5; + let dddfx = tmp2x * pre5; + let dddfy = tmp2y * pre5; + while (segments-- > 0) { + this.vertex(fx, fy, color); + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + this.vertex(fx, fy, color); + } + this.vertex(fx, fy, color); + this.vertex(x2, y2, color); + } + vertex(x, y, color) { + let idx = this.vertexIndex; + let vertices = this.mesh.getVertices(); + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color.r; + vertices[idx++] = color.g; + vertices[idx++] = color.b; + vertices[idx++] = color.a; + this.vertexIndex = idx; + } + end() { + if (!this.isDrawing) throw new Error("ShapeRenderer.begin() has not been called"); + this.flush(); + let gl = this.context.gl; + gl.disable(gl.BLEND); + this.isDrawing = false; + } + flush() { + if (this.vertexIndex == 0) return; + if (!this.shader) throw new Error("No shader set."); + this.mesh.setVerticesLength(this.vertexIndex); + this.mesh.draw(this.shader, this.shapeType); + this.vertexIndex = 0; + } + check(shapeType, numVertices) { + if (!this.isDrawing) throw new Error("ShapeRenderer.begin() has not been called"); + if (this.shapeType == shapeType) { + if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) this.flush(); + else return; + } else { + this.flush(); + this.shapeType = shapeType; + } + } + dispose() { + this.mesh.dispose(); + } + }; + var ShapeType = /* @__PURE__ */ ((ShapeType2) => { + ShapeType2[ShapeType2["Point"] = 0] = "Point"; + ShapeType2[ShapeType2["Line"] = 1] = "Line"; + ShapeType2[ShapeType2["Filled"] = 4] = "Filled"; + return ShapeType2; + })(ShapeType || {}); + + // spine-webgl/src/SkeletonDebugRenderer.ts + var SkeletonDebugRenderer = class _SkeletonDebugRenderer { + boneLineColor = new Color(1, 0, 0, 1); + boneOriginColor = new Color(0, 1, 0, 1); + attachmentLineColor = new Color(0, 0, 1, 0.5); + triangleLineColor = new Color(1, 0.64, 0, 0.5); + pathColor = new Color().setFromString("FF7F00"); + clipColor = new Color(0.8, 0, 0, 2); + aabbColor = new Color(0, 1, 0, 0.5); + drawBones = true; + drawRegionAttachments = true; + drawBoundingBoxes = true; + drawMeshHull = true; + drawMeshTriangles = true; + drawPaths = true; + drawSkeletonXY = false; + drawClipping = true; + premultipliedAlpha = false; + scale = 1; + boneWidth = 2; + context; + bounds = new SkeletonBounds(); + temp = new Array(); + vertices = Utils.newFloatArray(2 * 1024); + static LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1); + static GREEN = new Color(0, 1, 0, 1); + constructor(context) { + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + } + draw(shapes, skeleton, ignoredBones) { + let skeletonX = skeleton.x; + let skeletonY = skeleton.y; + let gl = this.context.gl; + let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; + shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + let bones = skeleton.bones; + if (this.drawBones) { + shapes.setColor(this.boneLineColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue; + if (!bone.parent) continue; + let x = bone.data.length * bone.a + bone.worldX; + let y = bone.data.length * bone.c + bone.worldY; + shapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale); + } + if (this.drawSkeletonXY) shapes.x(skeletonX, skeletonY, 4 * this.scale); + } + if (this.drawRegionAttachments) { + shapes.setColor(this.attachmentLineColor); + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + let vertices = this.vertices; + regionAttachment.computeWorldVertices(slot, vertices, 0, 2); + shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); + shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]); + shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]); + shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]); + } + } + } + if (this.drawMeshHull || this.drawMeshTriangles) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof MeshAttachment)) continue; + let mesh = attachment; + let vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2); + let triangles = mesh.triangles; + let hullLength = mesh.hullLength; + if (this.drawMeshTriangles) { + shapes.setColor(this.triangleLineColor); + for (let ii = 0, nn = triangles.length; ii < nn; ii += 3) { + let v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2; + shapes.triangle( + false, + vertices[v1], + vertices[v1 + 1], + // + vertices[v2], + vertices[v2 + 1], + // + vertices[v3], + vertices[v3 + 1] + // + ); + } + } + if (this.drawMeshHull && hullLength > 0) { + shapes.setColor(this.attachmentLineColor); + hullLength = (hullLength >> 1) * 2; + let lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1]; + for (let ii = 0, nn = hullLength; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + shapes.line(x, y, lastX, lastY); + lastX = x; + lastY = y; + } + } + } + } + if (this.drawBoundingBoxes) { + let bounds = this.bounds; + bounds.update(skeleton, true); + shapes.setColor(this.aabbColor); + shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight()); + let polygons = bounds.polygons; + let boxes = bounds.boundingBoxes; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + shapes.setColor(boxes[i].color); + shapes.polygon(polygon, 0, polygon.length); + } + } + if (this.drawPaths) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof PathAttachment)) continue; + let path = attachment; + let nn = path.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + path.computeWorldVertices(slot, 0, nn, world, 0, 2); + let color = this.pathColor; + let x1 = world[2], y1 = world[3], x2 = 0, y2 = 0; + if (path.closed) { + shapes.setColor(color); + let cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1]; + x2 = world[nn - 4]; + y2 = world[nn - 3]; + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + } + nn -= 4; + for (let ii = 4; ii < nn; ii += 6) { + let cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3]; + x2 = world[ii + 4]; + y2 = world[ii + 5]; + shapes.setColor(color); + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + x1 = x2; + y1 = y2; + } + } + } + if (this.drawBones) { + shapes.setColor(this.boneOriginColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue; + shapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8); + } + } + if (this.drawClipping) { + let slots = skeleton.slots; + shapes.setColor(this.clipColor); + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof ClippingAttachment)) continue; + let clip = attachment; + let nn = clip.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + clip.computeWorldVertices(slot, 0, nn, world, 0, 2); + for (let i2 = 0, n2 = world.length; i2 < n2; i2 += 2) { + let x = world[i2]; + let y = world[i2 + 1]; + let x2 = world[(i2 + 2) % world.length]; + let y2 = world[(i2 + 3) % world.length]; + shapes.line(x, y, x2, y2); + } + } + } + } + dispose() { + } + }; + + // spine-webgl/src/SkeletonRenderer.ts + var Renderable = class { + constructor(vertices, numVertices, numFloats) { + this.vertices = vertices; + this.numVertices = numVertices; + this.numFloats = numFloats; + } + }; + var SkeletonRenderer = class _SkeletonRenderer { + static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + premultipliedAlpha = false; + tempColor = new Color(); + tempColor2 = new Color(); + vertices; + vertexSize = 2 + 2 + 4; + twoColorTint = false; + renderable = new Renderable([], 0, 0); + clipper = new SkeletonClipping(); + temp = new Vector2(); + temp2 = new Vector2(); + temp3 = new Color(); + temp4 = new Color(); + constructor(context, twoColorTint = true) { + this.twoColorTint = twoColorTint; + if (twoColorTint) + this.vertexSize += 4; + this.vertices = Utils.newFloatArray(this.vertexSize * 1024); + } + draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1, transformer = null) { + let clipper = this.clipper; + let premultipliedAlpha = this.premultipliedAlpha; + let twoColorTint = this.twoColorTint; + let blendMode = null; + let renderable = this.renderable; + let uvs; + let triangles; + let drawOrder = skeleton.drawOrder; + let attachmentColor; + let skeletonColor = skeleton.color; + let vertexSize = twoColorTint ? 12 : 8; + let inRange = false; + if (slotRangeStart == -1) inRange = true; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize; + let slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) { + inRange = true; + } + if (!inRange) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) { + inRange = false; + } + let attachment = slot.getAttachment(); + let texture; + if (attachment instanceof RegionAttachment) { + let region = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = 4; + renderable.numFloats = clippedVertexSize << 2; + region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + uvs = region.uvs; + texture = region.region.texture; + attachmentColor = region.color; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = mesh.worldVerticesLength >> 1; + renderable.numFloats = renderable.numVertices * clippedVertexSize; + if (renderable.numFloats > renderable.vertices.length) { + renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats); + } + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize); + triangles = mesh.triangles; + texture = mesh.region.texture; + uvs = mesh.uvs; + attachmentColor = mesh.color; + } else if (attachment instanceof ClippingAttachment) { + let clip = attachment; + clipper.clipStart(slot, clip); + continue; + } else { + clipper.clipEndWithSlot(slot); + continue; + } + if (texture) { + let slotColor = slot.color; + let finalColor = this.tempColor; + finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r; + finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g; + finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b; + finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; + if (premultipliedAlpha) { + finalColor.r *= finalColor.a; + finalColor.g *= finalColor.a; + finalColor.b *= finalColor.a; + } + let darkColor = this.tempColor2; + if (!slot.darkColor) + darkColor.set(0, 0, 0, 1); + else { + if (premultipliedAlpha) { + darkColor.r = slot.darkColor.r * finalColor.a; + darkColor.g = slot.darkColor.g * finalColor.a; + darkColor.b = slot.darkColor.b * finalColor.a; + } else { + darkColor.setFromColor(slot.darkColor); + } + darkColor.a = premultipliedAlpha ? 1 : 0; + } + let slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + batcher.setBlendMode(blendMode, premultipliedAlpha); + } + if (clipper.isClipping()) { + clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint); + let clippedVertices = new Float32Array(clipper.clippedVertices); + let clippedTriangles = clipper.clippedTriangles; + if (transformer) transformer(clippedVertices, clippedVertices.length, vertexSize); + batcher.draw(texture, clippedVertices, clippedTriangles); + } else { + let verts = renderable.vertices; + if (!twoColorTint) { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + } + } else { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + verts[v + 6] = darkColor.r; + verts[v + 7] = darkColor.g; + verts[v + 8] = darkColor.b; + verts[v + 9] = darkColor.a; + } + } + let view = renderable.vertices.subarray(0, renderable.numFloats); + if (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize); + batcher.draw(texture, view, triangles); + } + } + clipper.clipEndWithSlot(slot); + } + clipper.clipEnd(); + } + /** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/ + getSkeletonClipping() { + return this.clipper; + } + }; + + // spine-webgl/src/SceneRenderer.ts + var quad = [ + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0 + ]; + var QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + var WHITE = new Color(1, 1, 1, 1); + var SceneRenderer = class { + context; + canvas; + camera; + batcher; + twoColorTint = false; + batcherShader; + shapes; + shapesShader; + activeRenderer = null; + skeletonRenderer; + skeletonDebugRenderer; + constructor(canvas, context, twoColorTint = true) { + this.canvas = canvas; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.twoColorTint = twoColorTint; + this.camera = new OrthoCamera(canvas.width, canvas.height); + this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); + this.batcher = new PolygonBatcher(this.context, twoColorTint); + this.shapesShader = Shader.newColored(this.context); + this.shapes = new ShapeRenderer(this.context); + this.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint); + this.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context); + } + dispose() { + this.batcher.dispose(); + this.batcherShader.dispose(); + this.shapes.dispose(); + this.shapesShader.dispose(); + this.skeletonDebugRenderer.dispose(); + } + begin() { + this.camera.update(); + this.enableRenderer(this.batcher); + } + drawSkeleton(skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform = null) { + this.enableRenderer(this.batcher); + this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform); + } + drawSkeletonDebug(skeleton, premultipliedAlpha = false, ignoredBones) { + this.enableRenderer(this.shapes); + this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones); + } + drawTexture(texture, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureUV(texture, x, y, width, height, u, v, u2, v2, color) { + this.enableRenderer(this.batcher); + if (!color) color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureRotated(texture, x, y, width, height, pivotX, pivotY, angle, color) { + this.enableRenderer(this.batcher); + if (!color) color = WHITE; + let worldOriginX = x + pivotX; + let worldOriginY = y + pivotY; + let fx = -pivotX; + let fy = -pivotY; + let fx2 = width - pivotX; + let fy2 = height - pivotY; + let p1x = fx; + let p1y = fy; + let p2x = fx; + let p2y = fy2; + let p3x = fx2; + let p3y = fy2; + let p4x = fx2; + let p4y = fy; + let x1 = 0; + let y1 = 0; + let x2 = 0; + let y2 = 0; + let x3 = 0; + let y3 = 0; + let x4 = 0; + let y4 = 0; + if (angle != 0) { + let cos = MathUtils.cosDeg(angle); + let sin = MathUtils.sinDeg(angle); + x1 = cos * p1x - sin * p1y; + y1 = sin * p1x + cos * p1y; + x4 = cos * p2x - sin * p2y; + y4 = sin * p2x + cos * p2y; + x3 = cos * p3x - sin * p3y; + y3 = sin * p3x + cos * p3y; + x2 = x3 + (x1 - x4); + y2 = y3 + (y1 - y4); + } else { + x1 = p1x; + y1 = p1y; + x4 = p2x; + y4 = p2y; + x3 = p3x; + y3 = p3y; + x2 = p4x; + y2 = p4y; + } + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + var i = 0; + quad[i++] = x1; + quad[i++] = y1; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x2; + quad[i++] = y2; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x3; + quad[i++] = y3; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x4; + quad[i++] = y4; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawRegion(region, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES); + } + line(x, y, x2, y2, color, color2) { + this.enableRenderer(this.shapes); + this.shapes.line(x, y, x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.enableRenderer(this.shapes); + this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3); + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.enableRenderer(this.shapes); + this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4); + } + rect(filled, x, y, width, height, color) { + this.enableRenderer(this.shapes); + this.shapes.rect(filled, x, y, width, height, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.enableRenderer(this.shapes); + this.shapes.rectLine(filled, x1, y1, x2, y2, width, color); + } + polygon(polygonVertices, offset, count, color) { + this.enableRenderer(this.shapes); + this.shapes.polygon(polygonVertices, offset, count, color); + } + circle(filled, x, y, radius, color, segments = 0) { + this.enableRenderer(this.shapes); + this.shapes.circle(filled, x, y, radius, color, segments); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.enableRenderer(this.shapes); + this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color); + } + end() { + if (this.activeRenderer === this.batcher) this.batcher.end(); + else if (this.activeRenderer === this.shapes) this.shapes.end(); + this.activeRenderer = null; + } + resize(resizeMode) { + let canvas = this.canvas; + var dpr = window.devicePixelRatio || 1; + var w = Math.round(canvas.clientWidth * dpr); + var h = Math.round(canvas.clientHeight * dpr); + if (canvas.width != w || canvas.height != h) { + canvas.width = w; + canvas.height = h; + } + this.context.gl.viewport(0, 0, canvas.width, canvas.height); + if (resizeMode === 1 /* Expand */) + this.camera.setViewport(w, h); + else if (resizeMode === 2 /* Fit */) { + let sourceWidth = canvas.width, sourceHeight = canvas.height; + let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight; + let targetRatio = targetHeight / targetWidth; + let sourceRatio = sourceHeight / sourceWidth; + let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; + this.camera.setViewport(sourceWidth * scale, sourceHeight * scale); + } + this.camera.update(); + } + enableRenderer(renderer) { + if (this.activeRenderer === renderer) return; + this.end(); + if (renderer instanceof PolygonBatcher) { + this.batcherShader.bind(); + this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.batcherShader.setUniformi("u_texture", 0); + this.batcher.begin(this.batcherShader); + this.activeRenderer = this.batcher; + } else if (renderer instanceof ShapeRenderer) { + this.shapesShader.bind(); + this.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.shapes.begin(this.shapesShader); + this.activeRenderer = this.shapes; + } else + this.activeRenderer = this.skeletonDebugRenderer; + } + }; + var ResizeMode = /* @__PURE__ */ ((ResizeMode2) => { + ResizeMode2[ResizeMode2["Stretch"] = 0] = "Stretch"; + ResizeMode2[ResizeMode2["Expand"] = 1] = "Expand"; + ResizeMode2[ResizeMode2["Fit"] = 2] = "Fit"; + return ResizeMode2; + })(ResizeMode || {}); + + // spine-webgl/src/LoadingScreen.ts + var spinnerImage; + var logoImage; + var loaded = 0; + var FADE_IN = 1; + var FADE_OUT = 1; + var logoWidth = 165; + var logoHeight = 108; + var spinnerSize = 163; + var LoadingScreen = class { + renderer; + logo = null; + spinner = null; + angle = 0; + fadeOut = 0; + fadeIn = 0; + timeKeeper = new TimeKeeper(); + backgroundColor = new Color(0.135, 0.135, 0.135, 1); + tempColor = new Color(); + constructor(renderer) { + this.renderer = renderer; + this.timeKeeper.maxDelta = 9; + if (!logoImage) { + let isSafari = navigator.userAgent.indexOf("Safari") > -1; + let onload = () => loaded++; + logoImage = new Image(); + logoImage.src = SPINE_LOGO_DATA; + if (!isSafari) logoImage.crossOrigin = "anonymous"; + logoImage.onload = onload; + spinnerImage = new Image(); + spinnerImage.src = SPINNER_DATA; + if (!isSafari) spinnerImage.crossOrigin = "anonymous"; + spinnerImage.onload = onload; + } + } + dispose() { + this.logo?.dispose(); + this.spinner?.dispose(); + } + draw(complete = false) { + if (loaded < 2 || complete && this.fadeOut > FADE_OUT) return; + this.timeKeeper.update(); + let a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25)); + this.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5)); + let tempColor = this.tempColor; + let renderer = this.renderer; + let canvas = renderer.canvas; + let gl = renderer.context.gl; + renderer.resize(1 /* Expand */); + renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); + renderer.batcher.setBlendMode(0 /* Normal */, true); + if (complete) { + this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); + if (this.fadeOut > FADE_OUT) return; + tempColor.setFromColor(this.backgroundColor); + a = 1 - this.fadeOut / FADE_OUT; + a = 1 - (a - 1) * (a - 1); + tempColor.a *= a; + if (tempColor.a > 0) { + renderer.camera.zoom = 1; + renderer.begin(); + renderer.quad( + true, + 0, + 0, + canvas.width, + 0, + canvas.width, + canvas.height, + 0, + canvas.height, + tempColor, + tempColor, + tempColor, + tempColor + ); + renderer.end(); + } + } else { + this.fadeIn += this.timeKeeper.delta; + if (this.backgroundColor.a > 0) { + gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a); + gl.clear(gl.COLOR_BUFFER_BIT); + } + a = 1; + } + a *= Math.min(this.fadeIn / FADE_IN, 1); + tempColor.set(a, a, a, a); + if (!this.logo) { + this.logo = new GLTexture(renderer.context, logoImage); + this.spinner = new GLTexture(renderer.context, spinnerImage); + } + renderer.camera.zoom = Math.max(1, spinnerSize / canvas.height); + renderer.begin(); + renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor); + if (this.spinner) renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor); + renderer.end(); + } + drawInCoordinates(x, y) { + if (loaded < 2) return; + this.timeKeeper.update(); + let renderer = this.renderer; + renderer.batcher.setBlendMode(0 /* Normal */, true); + if (!this.logo) { + this.logo = new GLTexture(renderer.context, logoImage); + this.spinner = new GLTexture(renderer.context, spinnerImage); + } + const shiftedX = x - logoWidth / 2; + const shiftedY = y - logoHeight / 2; + renderer.drawTexture(this.logo, shiftedX, shiftedY, logoWidth, logoHeight); + this.angle -= this.timeKeeper.delta * 500; + if (this.spinner) renderer.drawTextureRotated(this.spinner, shiftedX, shiftedY - 25, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle); + } + }; + var SPINNER_DATA = "data:image/png;base64,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"; + var SPINE_LOGO_DATA = "data:image/png;base64,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"; + + // spine-webgl/src/SpineCanvas.ts + var SpineCanvas = class { + /** Constructs a new spine canvas, rendering to the provided HTML canvas. */ + constructor(canvas, config) { + this.config = config; + if (!config.pathPrefix) config.pathPrefix = ""; + if (!config.app) config.app = { + loadAssets: () => { + }, + initialize: () => { + }, + update: () => { + }, + render: () => { + }, + error: () => { + }, + dispose: () => { + } + }; + if (!config.webglConfig) config.webglConfig = { alpha: true }; + this.htmlCanvas = canvas; + this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); + this.renderer = new SceneRenderer(canvas, this.context); + this.gl = this.context.gl; + this.assetManager = new AssetManager(this.context, config.pathPrefix); + this.input = new Input(canvas); + if (config.app.loadAssets) config.app.loadAssets(this); + let loop = () => { + if (this.disposed) return; + requestAnimationFrame(loop); + this.time.update(); + if (config.app.update) config.app.update(this, this.time.delta); + if (config.app.render) config.app.render(this); + }; + let waitForAssets = () => { + if (this.disposed) return; + if (this.assetManager.isLoadingComplete()) { + if (this.assetManager.hasErrors()) { + if (config.app.error) config.app.error(this, this.assetManager.getErrors()); + } else { + if (config.app.initialize) config.app.initialize(this); + loop(); + } + return; + } + requestAnimationFrame(waitForAssets); + }; + requestAnimationFrame(waitForAssets); + } + context; + /** Tracks the current time, delta, and other time related statistics. */ + time = new TimeKeeper(); + /** The HTML canvas to render to. */ + htmlCanvas; + /** The WebGL rendering context. */ + gl; + /** The scene renderer for easy drawing of skeletons, shapes, and images. */ + renderer; + /** The asset manager to load assets with. */ + assetManager; + /** The input processor used to listen to mouse, touch, and keyboard events. */ + input; + disposed = false; + /** Clears the canvas with the given color. The color values are given in the range [0,1]. */ + clear(r, g, b, a) { + this.gl.clearColor(r, g, b, a); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + } + /** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/ + dispose() { + if (this.config.app.dispose) this.config.app.dispose(this); + this.disposed = true; + } + }; + return __toCommonJS(index_exports); +})(); +//# sourceMappingURL=spine-webgl.js.map diff --git a/Spine插件/Spine_动画播放器_2.0/spine-webgl.js b/Spine插件/Spine_动画播放器_2.0/spine-webgl.js new file mode 100644 index 0000000..8d317c6 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/spine-webgl.js @@ -0,0 +1,11880 @@ +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-webgl/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, + CameraController: () => CameraController, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + Color2Attribute: () => Color2Attribute, + ColorAttribute: () => ColorAttribute, + 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, + GLTexture: () => GLTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + Input: () => Input, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + LoadingScreen: () => LoadingScreen, + M00: () => M00, + M01: () => M01, + M02: () => M02, + M03: () => M03, + M10: () => M10, + M11: () => M11, + M12: () => M12, + M13: () => M13, + M20: () => M20, + M21: () => M21, + M22: () => M22, + M23: () => M23, + M30: () => M30, + M31: () => M31, + M32: () => M32, + M33: () => M33, + ManagedWebGLRenderingContext: () => ManagedWebGLRenderingContext, + MathUtils: () => MathUtils, + Matrix4: () => Matrix42, + Mesh: () => Mesh, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + OrthoCamera: () => OrthoCamera, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + PointAttachment: () => PointAttachment, + PolygonBatcher: () => PolygonBatcher, + Pool: () => Pool, + Position2Attribute: () => Position2Attribute, + Position3Attribute: () => Position3Attribute, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + ResizeMode: () => ResizeMode, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + SceneRenderer: () => SceneRenderer, + SequenceTimeline: () => SequenceTimeline, + Shader: () => Shader, + ShapeRenderer: () => ShapeRenderer, + ShapeType: () => ShapeType, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonDebugRenderer: () => SkeletonDebugRenderer, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + SpineCanvas: () => SpineCanvas, + StringSet: () => StringSet, + TexCoordAttribute: () => TexCoordAttribute, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + Touch: () => Touch, + TrackEntry: () => TrackEntry, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TransformMode: () => TransformMode, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + Vector3: () => Vector3, + VertexAttachment: () => VertexAttachment, + VertexAttribute: () => VertexAttribute, + VertexAttributeType: () => VertexAttributeType, + WebGLBlendModeConverter: () => WebGLBlendModeConverter, + 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 = []; + this.worldVerticesLength = 0; + this.timelineAttachment = 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); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + } + }; + var VertexAttachment = _VertexAttachment; + VertexAttachment.nextID = 0; + + // spine-core/src/attachments/Sequence.ts + var _Sequence = class { + constructor(count) { + this.id = _Sequence.nextID(); + this.start = 0; + this.digits = 0; + this.setupIndex = 0; + 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; + Sequence._nextID = 0; + var SequenceMode; + (function(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"; + })(SequenceMode || (SequenceMode = {})); + var SequenceModeValues = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ]; + + // spine-core/src/Animation.ts + var Animation = class { + constructor(name, timelines, duration) { + this.timelines = []; + this.timelineIds = new StringSet(); + 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; + } + 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, + sequence: 19 + }; + var Timeline = class { + 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 { + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + 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.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) + return; + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != 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]) { + switch (blend) { + case 0: + deform.length = 0; + return; + case 1: + 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) { + 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 = 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 = 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 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; + 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; + } + } + }; + var _SequenceTimeline = class extends Timeline { + 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; + } + 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 || blend == 1) + 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 != SequenceMode.hold) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case SequenceMode.once: + index = Math.min(count - 1, index); + break; + case SequenceMode.loop: + index %= count; + break; + case SequenceMode.pingpong: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) + index = n - index; + break; + } + case SequenceMode.onceReverse: + index = Math.max(count - 1 - index, 0); + break; + case SequenceMode.loopReverse: + index = count - 1 - index % count; + break; + case SequenceMode.pingpongReverse: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) + index = n - index; + } + } + } + slot.sequenceIndex = index; + } + }; + var SequenceTimeline = _SequenceTimeline; + SequenceTimeline.ENTRIES = 3; + SequenceTimeline.MODE = 1; + SequenceTimeline.DELAY = 2; + + // spine-core/src/AnimationState.ts + var _AnimationState = class { + constructor(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 StringSet(); + this.animationsChanged = false; + this.trackEntryPool = new Pool(() => new TrackEntry()); + this.data = data; + } + static emptyAnimation() { + return _AnimationState._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 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 : MixBlend.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, 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 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 = 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 (!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 == 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.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 = 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 AnimationState = _AnimationState; + AnimationState._emptyAnimation = new Animation("", [], 0); + 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.shortestRotation = 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 = 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; + (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; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + constructor(skeletonData) { + 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(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"; + })(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 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 = TextureWrap.Repeat; + if (entry[1].indexOf("y") != -1) + page2.vWrap = TextureWrap.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() { + var _a; + for (let i = 0; i < this.pages.length; i++) { + (_a = this.pages[i].texture) == null ? void 0 : _a.dispose(); + } + } + }; + var TextureAtlasReader = class { + constructor(text) { + 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(name) { + 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; + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + } + }; + var TextureAtlasRegion = class extends TextureRegion { + constructor(page, name) { + super(); + 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; + this.page = page; + this.name = name; + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class extends VertexAttachment { + constructor(name, path) { + super(name); + this.region = null; + this.regionUVs = []; + this.uvs = []; + this.triangles = []; + this.color = new Color(1, 1, 1, 1); + this.width = 0; + this.height = 0; + this.hullLength = 0; + this.edges = []; + this.parentMesh = null; + this.sequence = null; + this.tempColor = new Color(0, 0, 0, 0); + this.path = path; + } + 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; + } + } + 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, 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, worldVertices, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices, offset, stride); + } + 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 { + constructor(name) { + super(name); + this.lengths = []; + 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, path) { + 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.rendererObject = null; + this.region = null; + this.sequence = null; + this.offset = Utils.newFloatArray(8); + this.uvs = Utils.newFloatArray(8); + this.tempColor = new Color(1, 1, 1, 1); + this.path = path; + } + 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; + } + } + computeWorldVertices(slot, worldVertices, 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]; + 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, this.path); + copy.region = this.region; + copy.rendererObject = this.rendererObject; + 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; + 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 = 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; + regions[i].renderObject = regions[i]; + } + } + 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 + ")"); + region.renderObject = region; + 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 + ")"); + region.renderObject = region; + 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.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.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 = new Downloader()) { + this.pathPrefix = ""; + this.assets = {}; + this.errors = {}; + this.toLoad = 0; + this.loaded = 0; + 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 { + 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.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.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.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++) { + 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; + } + } + 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 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; + 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 = 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; + } + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + }; + + // 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 = PositionMode.Fixed; + this.spacingMode = SpacingMode.Fixed; + this.rotateMode = RotateMode.Chain; + this.offsetRotation = 0; + this.position = 0; + this.spacing = 0; + this.mixRotate = 0; + this.mixX = 0; + this.mixY = 0; + } + set target(slotData) { + this._target = slotData; + } + get target() { + if (!this._target) + throw new Error("SlotData not set."); + else + return this._target; + } + }; + 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.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++) { + 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 == 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) : []; + 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 = 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 == 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.darkColor = null; + this.attachment = null; + this.attachmentState = 0; + this.sequenceIndex = -1; + 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.timelineAttachment != this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + 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.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++) { + 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.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._updateCache = new Array(); + this.skin = null; + 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) + 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; + } + } + 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(); + } + } + 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) { + let slot = this.data.findSlot(slotName); + if (!slot) + throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.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, 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); + } + }; + + // 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, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + }; + var Skin = class { + constructor(name) { + 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) + delete dictionary[name]; + } + 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.color = new Color(1, 1, 1, 1); + this.darkColor = null; + this.attachmentName = null; + this.blendMode = BlendMode.Normal; + 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; + } + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + constructor(attachmentLoader) { + this.scale = 1; + 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++) { + 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 == 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++) { + 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 == 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(); + 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 { + 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; + (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 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 { + 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(); + this.clipAttachment = null; + this.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; + } + } + } + } + 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 { + constructor(attachmentLoader) { + 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); + 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 == 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++) { + 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 == 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.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 { + 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-webgl/src/WebGL.ts + var ManagedWebGLRenderingContext = class { + constructor(canvasOrContext, contextConfig = { alpha: "true" }) { + this.restorables = new Array(); + if (!(canvasOrContext instanceof WebGLRenderingContext || typeof WebGL2RenderingContext !== "undefined" && canvasOrContext instanceof WebGL2RenderingContext)) { + let canvas = canvasOrContext; + this.gl = canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig); + this.canvas = canvas; + canvas.addEventListener("webglcontextlost", (e) => { + let event = e; + if (e) + e.preventDefault(); + }); + canvas.addEventListener("webglcontextrestored", (e) => { + for (let i = 0, n = this.restorables.length; i < n; i++) + this.restorables[i].restore(); + }); + } else { + this.gl = canvasOrContext; + this.canvas = this.gl.canvas; + } + } + addRestorable(restorable) { + this.restorables.push(restorable); + } + removeRestorable(restorable) { + let index = this.restorables.indexOf(restorable); + if (index > -1) + this.restorables.splice(index, 1); + } + }; + var ONE = 1; + var ONE_MINUS_SRC_COLOR = 769; + var SRC_ALPHA = 770; + var ONE_MINUS_SRC_ALPHA = 771; + var DST_COLOR = 774; + var WebGLBlendModeConverter = class { + static getDestGLBlendMode(blendMode) { + switch (blendMode) { + case BlendMode.Normal: + return ONE_MINUS_SRC_ALPHA; + case BlendMode.Additive: + return ONE; + case BlendMode.Multiply: + return ONE_MINUS_SRC_ALPHA; + case BlendMode.Screen: + return ONE_MINUS_SRC_ALPHA; + default: + throw new Error("Unknown blend mode: " + blendMode); + } + } + static getSourceColorGLBlendMode(blendMode, premultipliedAlpha = false) { + switch (blendMode) { + case BlendMode.Normal: + return premultipliedAlpha ? ONE : SRC_ALPHA; + case BlendMode.Additive: + return premultipliedAlpha ? ONE : SRC_ALPHA; + case BlendMode.Multiply: + return DST_COLOR; + case BlendMode.Screen: + return ONE; + default: + throw new Error("Unknown blend mode: " + blendMode); + } + } + static getSourceAlphaGLBlendMode(blendMode) { + switch (blendMode) { + case BlendMode.Normal: + return ONE; + case BlendMode.Additive: + return ONE; + case BlendMode.Multiply: + return ONE_MINUS_SRC_ALPHA; + case BlendMode.Screen: + return ONE_MINUS_SRC_COLOR; + default: + throw new Error("Unknown blend mode: " + blendMode); + } + } + }; + + // spine-webgl/src/GLTexture.ts + var _GLTexture = class extends Texture { + constructor(context, image, useMipMaps = false) { + super(image); + this.texture = null; + this.boundUnit = 0; + this.useMipMaps = false; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.useMipMaps = useMipMaps; + this.restore(); + this.context.addRestorable(this); + } + setFilters(minFilter, magFilter) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, _GLTexture.validateMagFilter(magFilter)); + this.useMipMaps = _GLTexture.usesMipMaps(minFilter); + if (this.useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + static validateMagFilter(magFilter) { + switch (magFilter) { + case TextureFilter.MipMap: + case TextureFilter.MipMapLinearLinear: + case TextureFilter.MipMapLinearNearest: + case TextureFilter.MipMapNearestLinear: + case TextureFilter.MipMapNearestNearest: + return TextureFilter.Linear; + default: + return magFilter; + } + } + static usesMipMaps(filter) { + switch (filter) { + case TextureFilter.MipMap: + case TextureFilter.MipMapLinearLinear: + case TextureFilter.MipMapLinearNearest: + case TextureFilter.MipMapNearestLinear: + case TextureFilter.MipMapNearestNearest: + return true; + default: + return false; + } + } + setWraps(uWrap, vWrap) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap); + } + update(useMipMaps) { + let gl = this.context.gl; + if (!this.texture) + this.texture = this.context.gl.createTexture(); + this.bind(); + if (_GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : 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); + if (useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + restore() { + this.texture = null; + this.update(this.useMipMaps); + } + bind(unit = 0) { + let gl = this.context.gl; + this.boundUnit = unit; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + } + unbind() { + let gl = this.context.gl; + gl.activeTexture(gl.TEXTURE0 + this.boundUnit); + gl.bindTexture(gl.TEXTURE_2D, null); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteTexture(this.texture); + } + }; + var GLTexture = _GLTexture; + GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false; + + // spine-webgl/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(context, pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new GLTexture(context, image); + }, pathPrefix, downloader); + } + }; + + // spine-webgl/src/Vector3.ts + var Vector3 = class { + constructor(x = 0, y = 0, z = 0) { + this.x = 0; + this.y = 0; + this.z = 0; + this.x = x; + this.y = y; + this.z = z; + } + setFrom(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + set(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + scale(s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + } + normalize() { + let len = this.length(); + if (len == 0) + return this; + len = 1 / len; + this.x *= len; + this.y *= len; + this.z *= len; + return this; + } + cross(v) { + return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + } + multiply(matrix) { + let l_mat = matrix.values; + return this.set(this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03], this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13], this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]); + } + project(matrix) { + let l_mat = matrix.values; + let l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]); + return this.set((this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w, (this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w, (this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w); + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + distance(v) { + let a = v.x - this.x; + let b = v.y - this.y; + let c = v.z - this.z; + return Math.sqrt(a * a + b * b + c * c); + } + }; + + // spine-webgl/src/Matrix4.ts + var M00 = 0; + var M01 = 4; + var M02 = 8; + var M03 = 12; + var M10 = 1; + var M11 = 5; + var M12 = 9; + var M13 = 13; + var M20 = 2; + var M21 = 6; + var M22 = 10; + var M23 = 14; + var M30 = 3; + var M31 = 7; + var M32 = 11; + var M33 = 15; + var _Matrix4 = class { + constructor() { + this.temp = new Float32Array(16); + this.values = new Float32Array(16); + let v = this.values; + v[M00] = 1; + v[M11] = 1; + v[M22] = 1; + v[M33] = 1; + } + set(values) { + this.values.set(values); + return this; + } + transpose() { + let t = this.temp; + let v = this.values; + t[M00] = v[M00]; + t[M01] = v[M10]; + t[M02] = v[M20]; + t[M03] = v[M30]; + t[M10] = v[M01]; + t[M11] = v[M11]; + t[M12] = v[M21]; + t[M13] = v[M31]; + t[M20] = v[M02]; + t[M21] = v[M12]; + t[M22] = v[M22]; + t[M23] = v[M32]; + t[M30] = v[M03]; + t[M31] = v[M13]; + t[M32] = v[M23]; + t[M33] = v[M33]; + return this.set(t); + } + identity() { + let v = this.values; + v[M00] = 1; + v[M01] = 0; + v[M02] = 0; + v[M03] = 0; + v[M10] = 0; + v[M11] = 1; + v[M12] = 0; + v[M13] = 0; + v[M20] = 0; + v[M21] = 0; + v[M22] = 1; + v[M23] = 0; + v[M30] = 0; + v[M31] = 0; + v[M32] = 0; + v[M33] = 1; + return this; + } + invert() { + let v = this.values; + let t = this.temp; + let l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + if (l_det == 0) + throw new Error("non-invertible matrix"); + let inv_det = 1 / l_det; + t[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32] - v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33]; + t[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32] + v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33]; + t[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32] - v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33]; + t[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22] + v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23]; + t[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32] + v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33]; + t[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32] - v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33]; + t[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32] + v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33]; + t[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22] - v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23]; + t[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31] - v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33]; + t[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31] + v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33]; + t[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31] - v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33]; + t[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21] + v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23]; + t[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31] + v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32]; + t[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31] - v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32]; + t[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31] + v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32]; + t[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21] - v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22]; + v[M00] = t[M00] * inv_det; + v[M01] = t[M01] * inv_det; + v[M02] = t[M02] * inv_det; + v[M03] = t[M03] * inv_det; + v[M10] = t[M10] * inv_det; + v[M11] = t[M11] * inv_det; + v[M12] = t[M12] * inv_det; + v[M13] = t[M13] * inv_det; + v[M20] = t[M20] * inv_det; + v[M21] = t[M21] * inv_det; + v[M22] = t[M22] * inv_det; + v[M23] = t[M23] * inv_det; + v[M30] = t[M30] * inv_det; + v[M31] = t[M31] * inv_det; + v[M32] = t[M32] * inv_det; + v[M33] = t[M33] * inv_det; + return this; + } + determinant() { + let v = this.values; + return v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + } + translate(x, y, z) { + let v = this.values; + v[M03] += x; + v[M13] += y; + v[M23] += z; + return this; + } + copy() { + return new _Matrix4().set(this.values); + } + projection(near, far, fovy, aspectRatio) { + this.identity(); + let l_fd = 1 / Math.tan(fovy * (Math.PI / 180) / 2); + let l_a1 = (far + near) / (near - far); + let l_a2 = 2 * far * near / (near - far); + let v = this.values; + v[M00] = l_fd / aspectRatio; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = l_fd; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = l_a1; + v[M32] = -1; + v[M03] = 0; + v[M13] = 0; + v[M23] = l_a2; + v[M33] = 0; + return this; + } + ortho2d(x, y, width, height) { + return this.ortho(x, x + width, y, y + height, 0, 1); + } + ortho(left, right, bottom, top, near, far) { + this.identity(); + let x_orth = 2 / (right - left); + let y_orth = 2 / (top - bottom); + let z_orth = -2 / (far - near); + let tx = -(right + left) / (right - left); + let ty = -(top + bottom) / (top - bottom); + let tz = -(far + near) / (far - near); + let v = this.values; + v[M00] = x_orth; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = y_orth; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = z_orth; + v[M32] = 0; + v[M03] = tx; + v[M13] = ty; + v[M23] = tz; + v[M33] = 1; + return this; + } + multiply(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30]; + t[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31]; + t[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32]; + t[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33]; + t[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30]; + t[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31]; + t[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32]; + t[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33]; + t[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30]; + t[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31]; + t[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32]; + t[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33]; + t[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30]; + t[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31]; + t[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32]; + t[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33]; + return this.set(this.temp); + } + multiplyLeft(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30]; + t[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31]; + t[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32]; + t[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33]; + t[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30]; + t[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31]; + t[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32]; + t[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33]; + t[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30]; + t[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31]; + t[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32]; + t[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33]; + t[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30]; + t[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31]; + t[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32]; + t[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33]; + return this.set(this.temp); + } + lookAt(position, direction, up) { + let xAxis = _Matrix4.xAxis, yAxis = _Matrix4.yAxis, zAxis = _Matrix4.zAxis; + zAxis.setFrom(direction).normalize(); + xAxis.setFrom(direction).normalize(); + xAxis.cross(up).normalize(); + yAxis.setFrom(xAxis).cross(zAxis).normalize(); + this.identity(); + let val = this.values; + val[M00] = xAxis.x; + val[M01] = xAxis.y; + val[M02] = xAxis.z; + val[M10] = yAxis.x; + val[M11] = yAxis.y; + val[M12] = yAxis.z; + val[M20] = -zAxis.x; + val[M21] = -zAxis.y; + val[M22] = -zAxis.z; + _Matrix4.tmpMatrix.identity(); + _Matrix4.tmpMatrix.values[M03] = -position.x; + _Matrix4.tmpMatrix.values[M13] = -position.y; + _Matrix4.tmpMatrix.values[M23] = -position.z; + this.multiply(_Matrix4.tmpMatrix); + return this; + } + }; + var Matrix42 = _Matrix4; + Matrix42.xAxis = new Vector3(); + Matrix42.yAxis = new Vector3(); + Matrix42.zAxis = new Vector3(); + Matrix42.tmpMatrix = new _Matrix4(); + + // spine-webgl/src/Camera.ts + var OrthoCamera = class { + constructor(viewportWidth, viewportHeight) { + this.position = new Vector3(0, 0, 0); + this.direction = new Vector3(0, 0, -1); + this.up = new Vector3(0, 1, 0); + this.near = 0; + this.far = 100; + this.zoom = 1; + this.viewportWidth = 0; + this.viewportHeight = 0; + this.projectionView = new Matrix42(); + this.inverseProjectionView = new Matrix42(); + this.projection = new Matrix42(); + this.view = new Matrix42(); + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.update(); + } + update() { + let projection = this.projection; + let view = this.view; + let projectionView = this.projectionView; + let inverseProjectionView = this.inverseProjectionView; + let zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight; + projection.ortho(zoom * (-viewportWidth / 2), zoom * (viewportWidth / 2), zoom * (-viewportHeight / 2), zoom * (viewportHeight / 2), this.near, this.far); + view.lookAt(this.position, this.direction, this.up); + projectionView.set(projection.values); + projectionView.multiply(view); + inverseProjectionView.set(projectionView.values).invert(); + } + screenToWorld(screenCoords, screenWidth, screenHeight) { + let x = screenCoords.x, y = screenHeight - screenCoords.y - 1; + screenCoords.x = 2 * x / screenWidth - 1; + screenCoords.y = 2 * y / screenHeight - 1; + screenCoords.z = 2 * screenCoords.z - 1; + screenCoords.project(this.inverseProjectionView); + return screenCoords; + } + worldToScreen(worldCoords, screenWidth, screenHeight) { + worldCoords.project(this.projectionView); + worldCoords.x = screenWidth * (worldCoords.x + 1) / 2; + worldCoords.y = screenHeight * (worldCoords.y + 1) / 2; + worldCoords.z = (worldCoords.z + 1) / 2; + return worldCoords; + } + setViewport(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + } + }; + + // spine-webgl/src/Input.ts + var Input = class { + constructor(element) { + this.mouseX = 0; + this.mouseY = 0; + this.buttonDown = false; + this.touch0 = null; + this.touch1 = null; + this.initialPinchDistance = 0; + this.listeners = new Array(); + this.eventListeners = []; + this.element = element; + this.setupCallbacks(element); + } + setupCallbacks(element) { + let mouseDown = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.mouseX, this.mouseY); + }); + document.addEventListener("mousemove", mouseMove); + document.addEventListener("mouseup", mouseUp); + } + }; + let mouseMove = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.listeners.map((listener) => { + if (this.buttonDown) { + if (listener.dragged) + listener.dragged(this.mouseX, this.mouseY); + } else { + if (listener.moved) + listener.moved(this.mouseX, this.mouseY); + } + }); + } + }; + let mouseUp = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = false; + this.listeners.map((listener) => { + if (listener.up) + listener.up(this.mouseX, this.mouseY); + }); + document.removeEventListener("mousemove", mouseMove); + document.removeEventListener("mouseup", mouseUp); + } + }; + let mouseWheel = (e) => { + e.preventDefault(); + let deltaY = e.deltaY; + if (e.deltaMode == WheelEvent.DOM_DELTA_LINE) + deltaY *= 8; + if (e.deltaMode == WheelEvent.DOM_DELTA_PAGE) + deltaY *= 24; + this.listeners.map((listener) => { + if (listener.wheel) + listener.wheel(e.deltaY); + }); + }; + element.addEventListener("mousedown", mouseDown, true); + element.addEventListener("mousemove", mouseMove, true); + element.addEventListener("mouseup", mouseUp, true); + element.addEventListener("wheel", mouseWheel, true); + element.addEventListener("touchstart", (ev) => { + if (!this.touch0 || !this.touch1) { + var touches = ev.changedTouches; + let nativeTouch = touches.item(0); + if (!nativeTouch) + return; + let rect = element.getBoundingClientRect(); + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + let touch = new Touch(nativeTouch.identifier, x, y); + this.mouseX = x; + this.mouseY = y; + this.buttonDown = true; + if (!this.touch0) { + this.touch0 = touch; + this.listeners.map((listener) => { + if (listener.down) + listener.down(touch.x, touch.y); + }); + } else if (!this.touch1) { + this.touch1 = touch; + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, this.initialPinchDistance); + }); + } + } + ev.preventDefault(); + }, false); + element.addEventListener("touchmove", (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0.x = this.mouseX = x; + this.touch0.y = this.mouseY = y; + this.listeners.map((listener) => { + if (listener.dragged) + listener.dragged(x, y); + }); + } + if (this.touch1 && this.touch1.identifier === nativeTouch.identifier) { + this.touch1.x = this.mouseX = x; + this.touch1.y = this.mouseY = y; + } + } + if (this.touch0 && this.touch1) { + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + let distance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, distance); + }); + } + } + ev.preventDefault(); + }, false); + let touchEnd = (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0 = null; + this.mouseX = x; + this.mouseY = y; + this.listeners.map((listener) => { + if (listener.up) + listener.up(x, y); + }); + if (!this.touch1) { + this.buttonDown = false; + break; + } else { + this.touch0 = this.touch1; + this.touch1 = null; + this.mouseX = this.touch0.x; + this.mouseX = this.touch0.x; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.touch0.x, this.touch0.y); + }); + } + } + if (this.touch1 && this.touch1.identifier) { + this.touch1 = null; + } + } + } + ev.preventDefault(); + }; + element.addEventListener("touchend", touchEnd, false); + element.addEventListener("touchcancel", touchEnd); + } + addListener(listener) { + this.listeners.push(listener); + } + removeListener(listener) { + let idx = this.listeners.indexOf(listener); + if (idx > -1) { + this.listeners.splice(idx, 1); + } + } + }; + var Touch = class { + constructor(identifier, x, y) { + this.identifier = identifier; + this.x = x; + this.y = y; + } + }; + + // spine-webgl/src/CameraController.ts + var CameraController = class { + constructor(canvas, camera) { + this.canvas = canvas; + this.camera = camera; + let cameraX = 0, cameraY = 0, cameraZoom = 0; + let mouseX = 0, mouseY = 0; + let lastX = 0, lastY = 0; + let initialZoom = 0; + new Input(canvas).addListener({ + down: (x, y) => { + cameraX = camera.position.x; + cameraY = camera.position.y; + mouseX = lastX = x; + mouseY = lastY = y; + initialZoom = camera.zoom; + }, + dragged: (x, y) => { + let deltaX = x - mouseX; + let deltaY = y - mouseY; + let originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight); + let deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld); + camera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0); + camera.update(); + lastX = x; + lastY = y; + }, + wheel: (delta) => { + let zoomAmount = delta / 200 * camera.zoom; + let newZoom = camera.zoom + zoomAmount; + if (newZoom > 0) { + let x = 0, y = 0; + if (delta < 0) { + x = lastX; + y = lastY; + } else { + let viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2); + let mouseToCenterX = lastX - viewCenter.x; + let mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y; + x = viewCenter.x - mouseToCenterX; + y = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY; + } + let oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.zoom = newZoom; + camera.update(); + let newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.position.add(oldDistance.sub(newDistance)); + camera.update(); + } + }, + zoom: (initialDistance, distance) => { + let newZoom = initialDistance / distance; + camera.zoom = initialZoom * newZoom; + }, + up: (x, y) => { + lastX = x; + lastY = y; + }, + moved: (x, y) => { + lastX = x; + lastY = y; + } + }); + } + }; + + // spine-webgl/src/Shader.ts + var _Shader = class { + constructor(context, vertexShader, fragmentShader) { + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.vs = null; + this.fs = null; + this.program = null; + this.tmp2x2 = new Float32Array(2 * 2); + this.tmp3x3 = new Float32Array(3 * 3); + this.tmp4x4 = new Float32Array(4 * 4); + this.vsSource = vertexShader; + this.fsSource = fragmentShader; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.context.addRestorable(this); + this.compile(); + } + getProgram() { + return this.program; + } + getVertexShader() { + return this.vertexShader; + } + getFragmentShader() { + return this.fragmentShader; + } + getVertexShaderSource() { + return this.vsSource; + } + getFragmentSource() { + return this.fsSource; + } + compile() { + let gl = this.context.gl; + try { + this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); + if (!this.vs) + throw new Error("Couldn't compile vertex shader."); + this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); + if (!this.fs) + throw new Error("Couldn#t compile fragment shader."); + this.program = this.compileProgram(this.vs, this.fs); + } catch (e) { + this.dispose(); + throw e; + } + } + compileShader(type, source) { + let gl = this.context.gl; + let shader = gl.createShader(type); + if (!shader) + throw new Error("Couldn't create shader."); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + if (!gl.isContextLost()) + throw new Error(error); + } + return shader; + } + compileProgram(vs, fs) { + let gl = this.context.gl; + let program = gl.createProgram(); + if (!program) + throw new Error("Couldn't compile program."); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); + gl.deleteProgram(program); + if (!gl.isContextLost()) + throw new Error(error); + } + return program; + } + restore() { + this.compile(); + } + bind() { + this.context.gl.useProgram(this.program); + } + unbind() { + this.context.gl.useProgram(null); + } + setUniformi(uniform, value) { + this.context.gl.uniform1i(this.getUniformLocation(uniform), value); + } + setUniformf(uniform, value) { + this.context.gl.uniform1f(this.getUniformLocation(uniform), value); + } + setUniform2f(uniform, value, value2) { + this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); + } + setUniform3f(uniform, value, value2, value3) { + this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); + } + setUniform4f(uniform, value, value2, value3, value4) { + this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); + } + setUniform2x2f(uniform, value) { + let gl = this.context.gl; + this.tmp2x2.set(value); + gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); + } + setUniform3x3f(uniform, value) { + let gl = this.context.gl; + this.tmp3x3.set(value); + gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); + } + setUniform4x4f(uniform, value) { + let gl = this.context.gl; + this.tmp4x4.set(value); + gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); + } + getUniformLocation(uniform) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getUniformLocation(this.program, uniform); + if (!location && !gl.isContextLost()) + throw new Error(`Couldn't find location for uniform ${uniform}`); + return location; + } + getAttributeLocation(attribute) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getAttribLocation(this.program, attribute); + if (location == -1 && !gl.isContextLost()) + throw new Error(`Couldn't find location for attribute ${attribute}`); + return location; + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + if (this.vs) { + gl.deleteShader(this.vs); + this.vs = null; + } + if (this.fs) { + gl.deleteShader(this.fs); + this.fs = null; + } + if (this.program) { + gl.deleteProgram(this.program); + this.program = null; + } + } + static newColoredTextured(context) { + let vs = ` + attribute vec4 ${_Shader.POSITION}; + attribute vec4 ${_Shader.COLOR}; + attribute vec2 ${_Shader.TEXCOORDS}; + uniform mat4 ${_Shader.MVP_MATRIX}; + varying vec4 v_color; + varying vec2 v_texCoords; + + void main () { + v_color = ${_Shader.COLOR}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; + } + `; + let fs = ` + #ifdef GL_ES + #define LOWP lowp + precision mediump float; + #else + #define LOWP + #endif + varying LOWP vec4 v_color; + varying vec2 v_texCoords; + uniform sampler2D u_texture; + + void main () { + gl_FragColor = v_color * texture2D(u_texture, v_texCoords); + } + `; + return new _Shader(context, vs, fs); + } + static newTwoColoredTextured(context) { + let vs = ` + attribute vec4 ${_Shader.POSITION}; + attribute vec4 ${_Shader.COLOR}; + attribute vec4 ${_Shader.COLOR2}; + attribute vec2 ${_Shader.TEXCOORDS}; + uniform mat4 ${_Shader.MVP_MATRIX}; + varying vec4 v_light; + varying vec4 v_dark; + varying vec2 v_texCoords; + + void main () { + v_light = ${_Shader.COLOR}; + v_dark = ${_Shader.COLOR2}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; + } + `; + let fs = ` + #ifdef GL_ES + #define LOWP lowp + precision mediump float; + #else + #define LOWP + #endif + varying LOWP vec4 v_light; + varying LOWP vec4 v_dark; + varying vec2 v_texCoords; + uniform sampler2D u_texture; + + void main () { + vec4 texColor = texture2D(u_texture, v_texCoords); + gl_FragColor.a = texColor.a * v_light.a; + gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; + } + `; + return new _Shader(context, vs, fs); + } + static newColored(context) { + let vs = ` + attribute vec4 ${_Shader.POSITION}; + attribute vec4 ${_Shader.COLOR}; + uniform mat4 ${_Shader.MVP_MATRIX}; + varying vec4 v_color; + + void main () { + v_color = ${_Shader.COLOR}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; + } + `; + let fs = ` + #ifdef GL_ES + #define LOWP lowp + precision mediump float; + #else + #define LOWP + #endif + varying LOWP vec4 v_color; + + void main () { + gl_FragColor = v_color; + } + `; + return new _Shader(context, vs, fs); + } + }; + var Shader = _Shader; + Shader.MVP_MATRIX = "u_projTrans"; + Shader.POSITION = "a_position"; + Shader.COLOR = "a_color"; + Shader.COLOR2 = "a_color2"; + Shader.TEXCOORDS = "a_texCoords"; + Shader.SAMPLER = "u_texture"; + + // spine-webgl/src/Mesh.ts + var Mesh = class { + constructor(context, attributes, maxVertices, maxIndices) { + this.attributes = attributes; + this.verticesBuffer = null; + this.verticesLength = 0; + this.dirtyVertices = false; + this.indicesBuffer = null; + this.indicesLength = 0; + this.dirtyIndices = false; + this.elementsPerVertex = 0; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.elementsPerVertex = 0; + for (let i = 0; i < attributes.length; i++) { + this.elementsPerVertex += attributes[i].numElements; + } + this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); + this.indices = new Uint16Array(maxIndices); + this.context.addRestorable(this); + } + getAttributes() { + return this.attributes; + } + maxVertices() { + return this.vertices.length / this.elementsPerVertex; + } + numVertices() { + return this.verticesLength / this.elementsPerVertex; + } + setVerticesLength(length) { + this.dirtyVertices = true; + this.verticesLength = length; + } + getVertices() { + return this.vertices; + } + maxIndices() { + return this.indices.length; + } + numIndices() { + return this.indicesLength; + } + setIndicesLength(length) { + this.dirtyIndices = true; + this.indicesLength = length; + } + getIndices() { + return this.indices; + } + getVertexSizeInFloats() { + let size = 0; + for (var i = 0; i < this.attributes.length; i++) { + let attribute = this.attributes[i]; + size += attribute.numElements; + } + return size; + } + setVertices(vertices) { + this.dirtyVertices = true; + if (vertices.length > this.vertices.length) + throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); + this.vertices.set(vertices, 0); + this.verticesLength = vertices.length; + } + setIndices(indices) { + this.dirtyIndices = true; + if (indices.length > this.indices.length) + throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); + this.indices.set(indices, 0); + this.indicesLength = indices.length; + } + draw(shader, primitiveType) { + this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); + } + drawWithOffset(shader, primitiveType, offset, count) { + let gl = this.context.gl; + if (this.dirtyVertices || this.dirtyIndices) + this.update(); + this.bind(shader); + if (this.indicesLength > 0) { + gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); + } else { + gl.drawArrays(primitiveType, offset, count); + } + this.unbind(shader); + } + bind(shader) { + let gl = this.context.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + let offset = 0; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); + offset += attrib.numElements; + } + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + } + unbind(shader) { + let gl = this.context.gl; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.disableVertexAttribArray(location); + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + } + update() { + let gl = this.context.gl; + if (this.dirtyVertices) { + if (!this.verticesBuffer) { + this.verticesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); + this.dirtyVertices = false; + } + if (this.dirtyIndices) { + if (!this.indicesBuffer) { + this.indicesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); + this.dirtyIndices = false; + } + } + restore() { + this.verticesBuffer = null; + this.indicesBuffer = null; + this.update(); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteBuffer(this.verticesBuffer); + gl.deleteBuffer(this.indicesBuffer); + } + }; + var VertexAttribute = class { + constructor(name, type, numElements) { + this.name = name; + this.type = type; + this.numElements = numElements; + } + }; + var Position2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 2); + } + }; + var Position3Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 3); + } + }; + var TexCoordAttribute = class extends VertexAttribute { + constructor(unit = 0) { + super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2); + } + }; + var ColorAttribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR, VertexAttributeType.Float, 4); + } + }; + var Color2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR2, VertexAttributeType.Float, 4); + } + }; + var VertexAttributeType; + (function(VertexAttributeType2) { + VertexAttributeType2[VertexAttributeType2["Float"] = 0] = "Float"; + })(VertexAttributeType || (VertexAttributeType = {})); + + // spine-webgl/src/PolygonBatcher.ts + var PolygonBatcher = class { + constructor(context, twoColorTint = true, maxVertices = 10920) { + this.drawCalls = 0; + this.isDrawing = false; + this.shader = null; + this.lastTexture = null; + this.verticesLength = 0; + this.indicesLength = 0; + this.cullWasEnabled = false; + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + let attributes = twoColorTint ? [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] : [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()]; + this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()"); + this.drawCalls = 0; + this.shader = shader; + this.lastTexture = null; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE); + if (this.cullWasEnabled) + gl.disable(gl.CULL_FACE); + } + setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) { + if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) + return; + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + } + draw(texture, vertices, indices) { + if (texture != this.lastTexture) { + this.flush(); + this.lastTexture = texture; + } else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || this.indicesLength + indices.length > this.mesh.getIndices().length) { + this.flush(); + } + let indexStart = this.mesh.numVertices(); + this.mesh.getVertices().set(vertices, this.verticesLength); + this.verticesLength += vertices.length; + this.mesh.setVerticesLength(this.verticesLength); + let indicesArray = this.mesh.getIndices(); + for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++) + indicesArray[i] = indices[j] + indexStart; + this.indicesLength += indices.length; + this.mesh.setIndicesLength(this.indicesLength); + } + flush() { + if (this.verticesLength == 0) + return; + if (!this.lastTexture) + throw new Error("No texture set."); + if (!this.shader) + throw new Error("No shader set."); + this.lastTexture.bind(); + this.mesh.draw(this.shader, this.context.gl.TRIANGLES); + this.verticesLength = 0; + this.indicesLength = 0; + this.mesh.setVerticesLength(0); + this.mesh.setIndicesLength(0); + this.drawCalls++; + } + end() { + if (!this.isDrawing) + throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()"); + if (this.verticesLength > 0 || this.indicesLength > 0) + this.flush(); + this.shader = null; + this.lastTexture = null; + this.isDrawing = false; + let gl = this.context.gl; + gl.disable(gl.BLEND); + if (this.cullWasEnabled) + gl.enable(gl.CULL_FACE); + } + getDrawCalls() { + return this.drawCalls; + } + dispose() { + this.mesh.dispose(); + } + }; + + // spine-webgl/src/ShapeRenderer.ts + var ShapeRenderer = class { + constructor(context, maxVertices = 10920) { + this.isDrawing = false; + this.shapeType = ShapeType.Filled; + this.color = new Color(1, 1, 1, 1); + this.shader = null; + this.vertexIndex = 0; + this.tmp = new Vector2(); + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("ShapeRenderer.begin() has already been called"); + this.shader = shader; + this.vertexIndex = 0; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + } + setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) { + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + } + setColor(color) { + this.color.setFromColor(color); + } + setColorWith(r, g, b, a) { + this.color.set(r, g, b, a); + } + point(x, y, color) { + this.check(ShapeType.Point, 1); + if (!color) + color = this.color; + this.vertex(x, y, color); + } + line(x, y, x2, y2, color) { + this.check(ShapeType.Line, 2); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + this.vertex(x, y, color); + this.vertex(x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color); + this.vertex(x3, y3, color2); + this.vertex(x3, y3, color); + this.vertex(x, y, color2); + } + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (!color4) + color4 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + } + rect(filled, x, y, width, height, color) { + this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 8); + if (!color) + color = this.color; + let t = this.tmp.set(y2 - y1, x1 - x2); + t.normalize(); + width *= 0.5; + let tx = t.x * width; + let ty = t.y * width; + if (!filled) { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } else { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + } + x(x, y, size) { + this.line(x - size, y - size, x + size, y + size); + this.line(x - size, y + size, x + size, y - size); + } + polygon(polygonVertices, offset, count, color) { + if (count < 3) + throw new Error("Polygon must contain at least 3 vertices"); + this.check(ShapeType.Line, count * 2); + if (!color) + color = this.color; + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + offset <<= 1; + count <<= 1; + let firstX = polygonVertices[offset]; + let firstY = polygonVertices[offset + 1]; + let last = offset + count; + for (let i = offset, n = offset + count - 2; i < n; i += 2) { + let x1 = polygonVertices[i]; + let y1 = polygonVertices[i + 1]; + let x2 = 0; + let y2 = 0; + if (i + 2 >= last) { + x2 = firstX; + y2 = firstY; + } else { + x2 = polygonVertices[i + 2]; + y2 = polygonVertices[i + 3]; + } + this.vertex(x1, y1, color); + this.vertex(x2, y2, color); + } + } + circle(filled, x, y, radius, color, segments = 0) { + if (segments == 0) + segments = Math.max(1, 6 * MathUtils.cbrt(radius) | 0); + if (segments <= 0) + throw new Error("segments must be > 0."); + if (!color) + color = this.color; + let angle = 2 * MathUtils.PI / segments; + let cos = Math.cos(angle); + let sin = Math.sin(angle); + let cx = radius, cy = 0; + if (!filled) { + this.check(ShapeType.Line, segments * 2 + 2); + for (let i = 0; i < segments; i++) { + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x + cx, y + cy, color); + } else { + this.check(ShapeType.Filled, segments * 3 + 3); + segments--; + for (let i = 0; i < segments; i++) { + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + } + let temp = cx; + cx = radius; + cy = 0; + this.vertex(x + cx, y + cy, color); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.check(ShapeType.Line, segments * 2 + 2); + if (!color) + color = this.color; + let subdiv_step = 1 / segments; + let subdiv_step2 = subdiv_step * subdiv_step; + let subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + let pre1 = 3 * subdiv_step; + let pre2 = 3 * subdiv_step2; + let pre4 = 6 * subdiv_step2; + let pre5 = 6 * subdiv_step3; + let tmp1x = x1 - cx1 * 2 + cx2; + let tmp1y = y1 - cy1 * 2 + cy2; + let tmp2x = (cx1 - cx2) * 3 - x1 + x2; + let tmp2y = (cy1 - cy2) * 3 - y1 + y2; + let fx = x1; + let fy = y1; + let dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + let dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + let ddfx = tmp1x * pre4 + tmp2x * pre5; + let ddfy = tmp1y * pre4 + tmp2y * pre5; + let dddfx = tmp2x * pre5; + let dddfy = tmp2y * pre5; + while (segments-- > 0) { + this.vertex(fx, fy, color); + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + this.vertex(fx, fy, color); + } + this.vertex(fx, fy, color); + this.vertex(x2, y2, color); + } + vertex(x, y, color) { + let idx = this.vertexIndex; + let vertices = this.mesh.getVertices(); + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color.r; + vertices[idx++] = color.g; + vertices[idx++] = color.b; + vertices[idx++] = color.a; + this.vertexIndex = idx; + } + end() { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + this.flush(); + let gl = this.context.gl; + gl.disable(gl.BLEND); + this.isDrawing = false; + } + flush() { + if (this.vertexIndex == 0) + return; + if (!this.shader) + throw new Error("No shader set."); + this.mesh.setVerticesLength(this.vertexIndex); + this.mesh.draw(this.shader, this.shapeType); + this.vertexIndex = 0; + } + check(shapeType, numVertices) { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + if (this.shapeType == shapeType) { + if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) + this.flush(); + else + return; + } else { + this.flush(); + this.shapeType = shapeType; + } + } + dispose() { + this.mesh.dispose(); + } + }; + var ShapeType; + (function(ShapeType2) { + ShapeType2[ShapeType2["Point"] = 0] = "Point"; + ShapeType2[ShapeType2["Line"] = 1] = "Line"; + ShapeType2[ShapeType2["Filled"] = 4] = "Filled"; + })(ShapeType || (ShapeType = {})); + + // spine-webgl/src/SkeletonDebugRenderer.ts + var _SkeletonDebugRenderer = class { + constructor(context) { + this.boneLineColor = new Color(1, 0, 0, 1); + this.boneOriginColor = new Color(0, 1, 0, 1); + this.attachmentLineColor = new Color(0, 0, 1, 0.5); + this.triangleLineColor = new Color(1, 0.64, 0, 0.5); + this.pathColor = new Color().setFromString("FF7F00"); + this.clipColor = new Color(0.8, 0, 0, 2); + this.aabbColor = new Color(0, 1, 0, 0.5); + this.drawBones = true; + this.drawRegionAttachments = true; + this.drawBoundingBoxes = true; + this.drawMeshHull = true; + this.drawMeshTriangles = true; + this.drawPaths = true; + this.drawSkeletonXY = false; + this.drawClipping = true; + this.premultipliedAlpha = false; + this.scale = 1; + this.boneWidth = 2; + this.bounds = new SkeletonBounds(); + this.temp = new Array(); + this.vertices = Utils.newFloatArray(2 * 1024); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + } + draw(shapes, skeleton, ignoredBones) { + let skeletonX = skeleton.x; + let skeletonY = skeleton.y; + let gl = this.context.gl; + let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; + shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + let bones = skeleton.bones; + if (this.drawBones) { + shapes.setColor(this.boneLineColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + if (!bone.parent) + continue; + let x = bone.data.length * bone.a + bone.worldX; + let y = bone.data.length * bone.c + bone.worldY; + shapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale); + } + if (this.drawSkeletonXY) + shapes.x(skeletonX, skeletonY, 4 * this.scale); + } + if (this.drawRegionAttachments) { + shapes.setColor(this.attachmentLineColor); + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + let vertices = this.vertices; + regionAttachment.computeWorldVertices(slot, vertices, 0, 2); + shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); + shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]); + shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]); + shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]); + } + } + } + if (this.drawMeshHull || this.drawMeshTriangles) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof MeshAttachment)) + continue; + let mesh = attachment; + let vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2); + let triangles = mesh.triangles; + let hullLength = mesh.hullLength; + if (this.drawMeshTriangles) { + shapes.setColor(this.triangleLineColor); + for (let ii = 0, nn = triangles.length; ii < nn; ii += 3) { + let v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2; + shapes.triangle(false, vertices[v1], vertices[v1 + 1], vertices[v2], vertices[v2 + 1], vertices[v3], vertices[v3 + 1]); + } + } + if (this.drawMeshHull && hullLength > 0) { + shapes.setColor(this.attachmentLineColor); + hullLength = (hullLength >> 1) * 2; + let lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1]; + for (let ii = 0, nn = hullLength; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + shapes.line(x, y, lastX, lastY); + lastX = x; + lastY = y; + } + } + } + } + if (this.drawBoundingBoxes) { + let bounds = this.bounds; + bounds.update(skeleton, true); + shapes.setColor(this.aabbColor); + shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight()); + let polygons = bounds.polygons; + let boxes = bounds.boundingBoxes; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + shapes.setColor(boxes[i].color); + shapes.polygon(polygon, 0, polygon.length); + } + } + if (this.drawPaths) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof PathAttachment)) + continue; + let path = attachment; + let nn = path.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + path.computeWorldVertices(slot, 0, nn, world, 0, 2); + let color = this.pathColor; + let x1 = world[2], y1 = world[3], x2 = 0, y2 = 0; + if (path.closed) { + shapes.setColor(color); + let cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1]; + x2 = world[nn - 4]; + y2 = world[nn - 3]; + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + } + nn -= 4; + for (let ii = 4; ii < nn; ii += 6) { + let cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3]; + x2 = world[ii + 4]; + y2 = world[ii + 5]; + shapes.setColor(color); + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + x1 = x2; + y1 = y2; + } + } + } + if (this.drawBones) { + shapes.setColor(this.boneOriginColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + shapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8); + } + } + if (this.drawClipping) { + let slots = skeleton.slots; + shapes.setColor(this.clipColor); + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof ClippingAttachment)) + continue; + let clip = attachment; + let nn = clip.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + clip.computeWorldVertices(slot, 0, nn, world, 0, 2); + for (let i2 = 0, n2 = world.length; i2 < n2; i2 += 2) { + let x = world[i2]; + let y = world[i2 + 1]; + let x2 = world[(i2 + 2) % world.length]; + let y2 = world[(i2 + 3) % world.length]; + shapes.line(x, y, x2, y2); + } + } + } + } + dispose() { + } + }; + var SkeletonDebugRenderer = _SkeletonDebugRenderer; + SkeletonDebugRenderer.LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1); + SkeletonDebugRenderer.GREEN = new Color(0, 1, 0, 1); + + // spine-webgl/src/SkeletonRenderer.ts + var Renderable = class { + constructor(vertices, numVertices, numFloats) { + this.vertices = vertices; + this.numVertices = numVertices; + this.numFloats = numFloats; + } + }; + var _SkeletonRenderer = class { + constructor(context, twoColorTint = true) { + this.premultipliedAlpha = false; + this.tempColor = new Color(); + this.tempColor2 = new Color(); + this.vertexSize = 2 + 2 + 4; + this.twoColorTint = false; + this.renderable = new Renderable([], 0, 0); + this.clipper = new SkeletonClipping(); + this.temp = new Vector2(); + this.temp2 = new Vector2(); + this.temp3 = new Color(); + this.temp4 = new Color(); + this.twoColorTint = twoColorTint; + if (twoColorTint) + this.vertexSize += 4; + this.vertices = Utils.newFloatArray(this.vertexSize * 1024); + } + draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1) { + let clipper = this.clipper; + let premultipliedAlpha = this.premultipliedAlpha; + let twoColorTint = this.twoColorTint; + let blendMode = null; + let tempPos = this.temp; + let tempUv = this.temp2; + let tempLight = this.temp3; + let tempDark = this.temp4; + let renderable = this.renderable; + let uvs; + let triangles; + let drawOrder = skeleton.drawOrder; + let attachmentColor; + let skeletonColor = skeleton.color; + let vertexSize = twoColorTint ? 12 : 8; + let inRange = false; + if (slotRangeStart == -1) + inRange = true; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize; + let slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) { + inRange = true; + } + if (!inRange) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) { + inRange = false; + } + let attachment = slot.getAttachment(); + let texture; + if (attachment instanceof RegionAttachment) { + let region = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = 4; + renderable.numFloats = clippedVertexSize << 2; + region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + uvs = region.uvs; + texture = region.region.renderObject.page.texture; + attachmentColor = region.color; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = mesh.worldVerticesLength >> 1; + renderable.numFloats = renderable.numVertices * clippedVertexSize; + if (renderable.numFloats > renderable.vertices.length) { + renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats); + } + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize); + triangles = mesh.triangles; + texture = mesh.region.renderObject.page.texture; + uvs = mesh.uvs; + attachmentColor = mesh.color; + } else if (attachment instanceof ClippingAttachment) { + let clip = attachment; + clipper.clipStart(slot, clip); + continue; + } else { + clipper.clipEndWithSlot(slot); + continue; + } + if (texture) { + let slotColor = slot.color; + let finalColor = this.tempColor; + finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r; + finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g; + finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b; + finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; + if (premultipliedAlpha) { + finalColor.r *= finalColor.a; + finalColor.g *= finalColor.a; + finalColor.b *= finalColor.a; + } + let darkColor = this.tempColor2; + if (!slot.darkColor) + darkColor.set(0, 0, 0, 1); + else { + if (premultipliedAlpha) { + darkColor.r = slot.darkColor.r * finalColor.a; + darkColor.g = slot.darkColor.g * finalColor.a; + darkColor.b = slot.darkColor.b * finalColor.a; + } else { + darkColor.setFromColor(slot.darkColor); + } + darkColor.a = premultipliedAlpha ? 1 : 0; + } + let slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + batcher.setBlendMode(WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha), WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode), WebGLBlendModeConverter.getDestGLBlendMode(blendMode)); + } + if (clipper.isClipping()) { + clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint); + let clippedVertices = new Float32Array(clipper.clippedVertices); + let clippedTriangles = clipper.clippedTriangles; + batcher.draw(texture, clippedVertices, clippedTriangles); + } else { + let verts = renderable.vertices; + if (!twoColorTint) { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + } + } else { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + verts[v + 6] = darkColor.r; + verts[v + 7] = darkColor.g; + verts[v + 8] = darkColor.b; + verts[v + 9] = darkColor.a; + } + } + let view = renderable.vertices.subarray(0, renderable.numFloats); + batcher.draw(texture, view, triangles); + } + } + clipper.clipEndWithSlot(slot); + } + clipper.clipEnd(); + } + }; + var SkeletonRenderer = _SkeletonRenderer; + SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + + // spine-webgl/src/SceneRenderer.ts + var quad = [ + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0 + ]; + var QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + var WHITE = new Color(1, 1, 1, 1); + var SceneRenderer = class { + constructor(canvas, context, twoColorTint = true) { + this.twoColorTint = false; + this.activeRenderer = null; + this.canvas = canvas; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.twoColorTint = twoColorTint; + this.camera = new OrthoCamera(canvas.width, canvas.height); + this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); + this.batcher = new PolygonBatcher(this.context, twoColorTint); + this.shapesShader = Shader.newColored(this.context); + this.shapes = new ShapeRenderer(this.context); + this.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint); + this.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context); + } + dispose() { + this.batcher.dispose(); + this.batcherShader.dispose(); + this.shapes.dispose(); + this.shapesShader.dispose(); + this.skeletonDebugRenderer.dispose(); + } + begin() { + this.camera.update(); + this.enableRenderer(this.batcher); + } + drawSkeleton(skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1) { + this.enableRenderer(this.batcher); + this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd); + } + drawSkeletonDebug(skeleton, premultipliedAlpha = false, ignoredBones) { + this.enableRenderer(this.shapes); + this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones); + } + drawTexture(texture, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureUV(texture, x, y, width, height, u, v, u2, v2, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureRotated(texture, x, y, width, height, pivotX, pivotY, angle, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + let worldOriginX = x + pivotX; + let worldOriginY = y + pivotY; + let fx = -pivotX; + let fy = -pivotY; + let fx2 = width - pivotX; + let fy2 = height - pivotY; + let p1x = fx; + let p1y = fy; + let p2x = fx; + let p2y = fy2; + let p3x = fx2; + let p3y = fy2; + let p4x = fx2; + let p4y = fy; + let x1 = 0; + let y1 = 0; + let x2 = 0; + let y2 = 0; + let x3 = 0; + let y3 = 0; + let x4 = 0; + let y4 = 0; + if (angle != 0) { + let cos = MathUtils.cosDeg(angle); + let sin = MathUtils.sinDeg(angle); + x1 = cos * p1x - sin * p1y; + y1 = sin * p1x + cos * p1y; + x4 = cos * p2x - sin * p2y; + y4 = sin * p2x + cos * p2y; + x3 = cos * p3x - sin * p3y; + y3 = sin * p3x + cos * p3y; + x2 = x3 + (x1 - x4); + y2 = y3 + (y1 - y4); + } else { + x1 = p1x; + y1 = p1y; + x4 = p2x; + y4 = p2y; + x3 = p3x; + y3 = p3y; + x2 = p4x; + y2 = p4y; + } + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + var i = 0; + quad[i++] = x1; + quad[i++] = y1; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x2; + quad[i++] = y2; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x3; + quad[i++] = y3; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x4; + quad[i++] = y4; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawRegion(region, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES); + } + line(x, y, x2, y2, color, color2) { + this.enableRenderer(this.shapes); + this.shapes.line(x, y, x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.enableRenderer(this.shapes); + this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3); + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.enableRenderer(this.shapes); + this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4); + } + rect(filled, x, y, width, height, color) { + this.enableRenderer(this.shapes); + this.shapes.rect(filled, x, y, width, height, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.enableRenderer(this.shapes); + this.shapes.rectLine(filled, x1, y1, x2, y2, width, color); + } + polygon(polygonVertices, offset, count, color) { + this.enableRenderer(this.shapes); + this.shapes.polygon(polygonVertices, offset, count, color); + } + circle(filled, x, y, radius, color, segments = 0) { + this.enableRenderer(this.shapes); + this.shapes.circle(filled, x, y, radius, color, segments); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.enableRenderer(this.shapes); + this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color); + } + end() { + if (this.activeRenderer === this.batcher) + this.batcher.end(); + else if (this.activeRenderer === this.shapes) + this.shapes.end(); + this.activeRenderer = null; + } + resize(resizeMode) { + let canvas = this.canvas; + var dpr = window.devicePixelRatio || 1; + var w = Math.round(canvas.clientWidth * dpr); + var h = Math.round(canvas.clientHeight * dpr); + if (canvas.width != w || canvas.height != h) { + canvas.width = w; + canvas.height = h; + } + this.context.gl.viewport(0, 0, canvas.width, canvas.height); + if (resizeMode === ResizeMode.Expand) + this.camera.setViewport(w, h); + else if (resizeMode === ResizeMode.Fit) { + let sourceWidth = canvas.width, sourceHeight = canvas.height; + let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight; + let targetRatio = targetHeight / targetWidth; + let sourceRatio = sourceHeight / sourceWidth; + let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; + this.camera.setViewport(sourceWidth * scale, sourceHeight * scale); + } + this.camera.update(); + } + enableRenderer(renderer) { + if (this.activeRenderer === renderer) + return; + this.end(); + if (renderer instanceof PolygonBatcher) { + this.batcherShader.bind(); + this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.batcherShader.setUniformi("u_texture", 0); + this.batcher.begin(this.batcherShader); + this.activeRenderer = this.batcher; + } else if (renderer instanceof ShapeRenderer) { + this.shapesShader.bind(); + this.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.shapes.begin(this.shapesShader); + this.activeRenderer = this.shapes; + } else + this.activeRenderer = this.skeletonDebugRenderer; + } + }; + var ResizeMode; + (function(ResizeMode2) { + ResizeMode2[ResizeMode2["Stretch"] = 0] = "Stretch"; + ResizeMode2[ResizeMode2["Expand"] = 1] = "Expand"; + ResizeMode2[ResizeMode2["Fit"] = 2] = "Fit"; + })(ResizeMode || (ResizeMode = {})); + + // spine-webgl/src/LoadingScreen.ts + var spinnerImage; + var logoImage; + var loaded = 0; + var FADE_IN = 1; + var FADE_OUT = 1; + var logoWidth = 165; + var logoHeight = 108; + var spinnerSize = 163; + var LoadingScreen = class { + constructor(renderer) { + this.logo = null; + this.spinner = null; + this.angle = 0; + this.fadeOut = 0; + this.fadeIn = 0; + this.timeKeeper = new TimeKeeper(); + this.backgroundColor = new Color(0.135, 0.135, 0.135, 1); + this.tempColor = new Color(); + this.renderer = renderer; + this.timeKeeper.maxDelta = 9; + if (!logoImage) { + let isSafari = navigator.userAgent.indexOf("Safari") > -1; + let onload = () => loaded++; + logoImage = new Image(); + logoImage.src = SPINE_LOGO_DATA; + if (!isSafari) + logoImage.crossOrigin = "anonymous"; + logoImage.onload = onload; + spinnerImage = new Image(); + spinnerImage.src = SPINNER_DATA; + if (!isSafari) + spinnerImage.crossOrigin = "anonymous"; + spinnerImage.onload = onload; + } + } + dispose() { + var _a, _b; + (_a = this.logo) == null ? void 0 : _a.dispose(); + (_b = this.spinner) == null ? void 0 : _b.dispose(); + } + draw(complete = false) { + if (loaded < 2 || complete && this.fadeOut > FADE_OUT) + return; + this.timeKeeper.update(); + let a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25)); + this.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5)); + let tempColor = this.tempColor; + let renderer = this.renderer; + let canvas = renderer.canvas; + let gl = renderer.context.gl; + renderer.resize(ResizeMode.Expand); + renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); + renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + if (complete) { + this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); + if (this.fadeOut > FADE_OUT) + return; + tempColor.setFromColor(this.backgroundColor); + a = 1 - this.fadeOut / FADE_OUT; + a = 1 - (a - 1) * (a - 1); + tempColor.a *= a; + if (tempColor.a > 0) { + renderer.camera.zoom = 1; + renderer.begin(); + renderer.quad(true, 0, 0, canvas.width, 0, canvas.width, canvas.height, 0, canvas.height, tempColor, tempColor, tempColor, tempColor); + renderer.end(); + } + } else { + this.fadeIn += this.timeKeeper.delta; + if (this.backgroundColor.a > 0) { + gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a); + gl.clear(gl.COLOR_BUFFER_BIT); + } + a = 1; + } + a *= Math.min(this.fadeIn / FADE_IN, 1); + tempColor.set(a, a, a, a); + if (!this.logo) { + this.logo = new GLTexture(renderer.context, logoImage); + this.spinner = new GLTexture(renderer.context, spinnerImage); + } + renderer.camera.zoom = Math.max(1, spinnerSize / canvas.height); + renderer.begin(); + renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor); + if (this.spinner) + renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor); + renderer.end(); + } + }; + var SPINNER_DATA = "data:image/png;base64,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"; + var SPINE_LOGO_DATA = "data:image/png;base64,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"; + + // spine-webgl/src/SpineCanvas.ts + var SpineCanvas = class { + constructor(canvas, config) { + this.time = new TimeKeeper(); + if (!config.pathPrefix) + config.pathPrefix = ""; + if (!config.app) + config.app = { + loadAssets: () => { + }, + initialize: () => { + }, + update: () => { + }, + render: () => { + }, + error: () => { + } + }; + if (config.webglConfig) + config.webglConfig = { alpha: true }; + this.htmlCanvas = canvas; + this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); + this.renderer = new SceneRenderer(canvas, this.context); + this.gl = this.context.gl; + this.assetManager = new AssetManager(this.context, config.pathPrefix); + this.input = new Input(canvas); + if (config.app.loadAssets) + config.app.loadAssets(this); + let loop = () => { + requestAnimationFrame(loop); + this.time.update(); + if (config.app.update) + config.app.update(this, this.time.delta); + if (config.app.render) + config.app.render(this); + }; + let waitForAssets = () => { + if (this.assetManager.isLoadingComplete()) { + if (this.assetManager.hasErrors()) { + if (config.app.error) + config.app.error(this, this.assetManager.getErrors()); + } else { + if (config.app.initialize) + config.app.initialize(this); + loop(); + } + return; + } + requestAnimationFrame(waitForAssets); + }; + requestAnimationFrame(waitForAssets); + } + clear(r, g, b, a) { + this.gl.clearColor(r, g, b, a); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + } + }; + return src_exports; +})(); +//# sourceMappingURL=spine-webgl.js.map diff --git a/Spine插件/Spine_动画播放器_2.0/viewer_3.8.html b/Spine插件/Spine_动画播放器_2.0/viewer_3.8.html new file mode 100644 index 0000000..6489c5c --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/viewer_3.8.html @@ -0,0 +1,302 @@ + + + + + Spine 3.8 Core + + + + + +

⏳ 初始化内核...
+
+ +
+
SPINE 3.8 DETECTED
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + + diff --git a/Spine插件/Spine_动画播放器_2.0/viewer_4.1.html b/Spine插件/Spine_动画播放器_2.0/viewer_4.1.html new file mode 100644 index 0000000..2205a7c --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/viewer_4.1.html @@ -0,0 +1,302 @@ + + + + + Spine 4.1 Core + + + + + +
⏳ 初始化内核...
+
+ +
+
SPINE 4.1 DETECTED
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + + diff --git a/Spine插件/Spine_动画播放器_2.0/viewer_4.2.html b/Spine插件/Spine_动画播放器_2.0/viewer_4.2.html new file mode 100644 index 0000000..32f7a71 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/viewer_4.2.html @@ -0,0 +1,422 @@ + + + + + Spine 4.2 独立播放器 (V30) + + + + + +
+
🔥
+

Spine 4.2 独立播放器

+

支持格式:.json / .skel (4.2+)

+

请选择包含 骨架文件 + .atlas + .png 的文件夹

+ + + + +
+ + +
+
+ +
+ +
+
SPINE 4.2 PRO
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+ + + +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
系统就绪 (V30 独立版)...
+ + + + + diff --git a/Spine插件/Spine_动画播放器_2.0/使用说明.txt b/Spine插件/Spine_动画播放器_2.0/使用说明.txt new file mode 100644 index 0000000..842fe85 --- /dev/null +++ b/Spine插件/Spine_动画播放器_2.0/使用说明.txt @@ -0,0 +1,71 @@ +介绍:https://www.bilibili.com/video/BV1vgmQBWEfa +================================================================ + Spine 播放器 (Spine Universal Viewer) 使用说明书 +================================================================ + +感谢您使用本软件!这是一款支持全版本 (3.8 / 4.1 / 4.2) 的 Spine 动画查看与导出工具。 +无需安装,解压即用。 + +【快速开始】 + +1. 启动软件: + 直接双击文件夹里的 "index.html" 文件。 + (推荐使用 Chrome 谷歌浏览器 或 Edge 浏览器打开,体验最好) + +2. 加载动画: + 点击屏幕中间蓝色的 "📂 打开动画文件夹" 按钮。 + 选中包含 Spine 文件的文件夹即可。 + + ★ 注意:您的文件夹里必须包含以下三个文件才能成功加载: + - xxx.json 或 xxx.skel (骨骼数据) + - xxx.atlas (图集数据) + - xxx.png (图片纹理) + +================================================================ +【功能详解】 + +[1] 左上角面板:导出与重置 +------------------------------------------------ +● 🔄 重置 / 打开新文件 + 点击此按钮返回启动页,加载新的动画。 + +● 📂 导出序列帧 + 可以将当前的动画动作,导出为透明背景的 PNG 图片序列。 + - 前缀:设置导出文件名的开头(如 "atk",导出就是 atk_000.png)。 + - 编号:设置序号的位数。 + - 缩放:设置图片大小。输入 "1.0" 是原大,输入 "2.0" 是两倍高清大图。 + - 点击导出按钮后,会弹出一个窗口让您选择保存位置,然后自动开始录制。 + +[2] 右上角面板:外观设置 +------------------------------------------------ +● 选择动画:切换角色的动作(如待机、攻击、跑步)。 +● 选择皮肤:切换角色的皮肤(如果有)。 +● 显示骨骼:勾选后会显示绿色的骨骼线条,方便看结构。 +● PMA (预乘Alpha):★重要功能★ + 如果发现角色边缘有奇怪的黑边或白边,请尝试勾选或取消勾选这个框。 + 不同版本的 Spine 导出设置不同,切换这个选项通常能解决边缘显示问题。 + +[3] 底部面板:播放控制 +------------------------------------------------ +● 播放/暂停:控制动画播放。 +● 进度条:可以手动拖拽查看每一帧。 +● 倍速:从 0.5x (慢动作) 到 2.0x (快进) 只有选择。 +● 帧率:建议选择 60 FPS 以获得最流畅的体验。 +● 归位:如果把角色拖出屏幕找不到了,点一下这个按钮,角色会回到画面中心。 + +================================================================ +【常见问题】 + +Q:为什么打开是黑屏? +A:请检查是否使用了极速浏览器或旧版IE,请务必使用 Chrome 或 Edge。 + 另外,请确认文件夹里是否齐备了 .json/.skel + .atlas + .png 三个文件。 + +Q:怎么换成我自己的 Logo? +A:很简单!把您设计好的图片重命名为 "icon.png",放入本软件的文件夹里。 + 刷新一下网页,启动页的钻石图标就会变成您的图片了。 + +Q:Spine 4.2 的物理效果好像卡住了? +A:加载 4.2 模型时,右上角会出现红色的 "重置物理" 按钮,点一下它即可复位。 + +================================================================ +祝您使用愉快! diff --git a/压缩包/au3脚本/视频转码.au3 b/压缩包/au3脚本/视频转码.au3 new file mode 100644 index 0000000..8cb8b22 --- /dev/null +++ b/压缩包/au3脚本/视频转码.au3 @@ -0,0 +1,241 @@ +; HLS_Batch_Converter_Multi.au3 +; 支持最多 8 个并发转码 + 实时显示 ffmpeg 日志 + +#include +#include +#include +#include +#include + +; ========== 配置 ========== +Global Const $MAX_CONCURRENT = 8 + +; ========== 全局变量 ========== +Global $g_sSourceDir = "" +Global $g_hLogEdit, $g_hBtnStart, $g_hBtnSelect, $g_hLabelStatus + +; 任务队列和运行中任务 +Global $g_aPendingFiles[0] ; 待处理文件列表 (完整路径) +Global $g_aRunningTasks[0][4] ; [PID, FileName, OutputDir, LogHandle] +Global $g_iSuccess = 0 +Global $g_bConverting = False + +; ========== 创建主窗口 ========== +GUICreate("HLS 批量转码工具 - 多线程版", 700, 550) +GUICtrlCreateLabel("1. 请选择包含视频文件的源目录:", 10, 10, 400, 20) + +$g_hBtnSelect = GUICtrlCreateButton("选择目录...", 10, 35, 100, 30) +$g_hLabelStatus = GUICtrlCreateLabel("", 120, 40, 570, 20) +GUICtrlSetColor(-1, 0x0000FF) + +GUICtrlCreateLabel("2. 点击“开始转码”(最多 " & $MAX_CONCURRENT & " 个并发):", 10, 75, 400, 20) +$g_hBtnStart = GUICtrlCreateButton("开始转码", 10, 100, 100, 30) +GUICtrlSetState($g_hBtnStart, $GUI_DISABLE) + +GUICtrlCreateLabel("实时日志(格式: [视频名] 日志内容):", 10, 140, 300, 20) +$g_hLogEdit = GUICtrlCreateEdit("", 10, 165, 680, 370, BitOR($ES_AUTOVSCROLL, $ES_READONLY, $WS_VSCROLL)) +GUICtrlSetFont($g_hLogEdit, 9, 400, 0, "Consolas") + +GUISetState(@SW_SHOW) + +; ========== 消息循环 ========== +While 1 + Switch GUIGetMsg() + Case $GUI_EVENT_CLOSE + ; 清理子进程 + _KillAllRunningTasks() + Exit + Case $g_hBtnSelect + _SelectSourceDir() + Case $g_hBtnStart + _StartConversion() + EndSwitch + + ; 如果正在转码,定期检查任务状态(模拟异步) + If $g_bConverting Then + _PollRunningTasks() + Sleep(50) ; 减轻 CPU 占用 + EndIf +WEnd + +; ========== 函数定义 ========== +Func _SelectSourceDir() + Local $sDir = FileSelectFolder("请选择视频所在的源目录", "") + If Not @error And $sDir <> "" Then + $g_sSourceDir = $sDir + GUICtrlSetData($g_hLabelStatus, "已选择: " & $g_sSourceDir) + GUICtrlSetState($g_hBtnStart, $GUI_ENABLE) + _Log("✅ 目录已选择:" & $g_sSourceDir) + Else + $g_sSourceDir = "" + GUICtrlSetData($g_hLabelStatus, "未选择目录") + GUICtrlSetState($g_hBtnStart, $GUI_DISABLE) + EndIf +EndFunc + +Func _StartConversion() + If $g_sSourceDir = "" Or $g_bConverting Then Return + + $g_bConverting = True + GUICtrlSetState($g_hBtnStart, $GUI_DISABLE) + GUICtrlSetState($g_hBtnSelect, $GUI_DISABLE) + _Log(@CRLF & "🚀 开始批量转码(最多 " & $MAX_CONCURRENT & " 个并发)..." & @CRLF) + + ; 初始化 + $g_iSuccess = 0 + Dim $g_aPendingFiles[0] + Dim $g_aRunningTasks[0][4] + + ; 获取视频文件列表 + Local $aExtensions = [".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".mpeg", ".mpg", ".webm"] + Local $aFiles = _FileListToArray($g_sSourceDir, "*", $FLTA_FILES) + If @error Then + _Log("❌ 目录中没有找到任何文件。") + _FinishConversion() + Return + EndIf + + ; 填充待处理队列 + For $i = 1 To $aFiles[0] + Local $sFile = $g_sSourceDir & "\" & $aFiles[$i] + Local $sExt = StringLower(StringRight($sFile, 4)) + If _IsInArray($aExtensions, $sExt) Then + _ArrayAdd($g_aPendingFiles, $sFile) + EndIf + Next + + If UBound($g_aPendingFiles) = 0 Then + _Log("❌ 未找到支持的视频文件。") + _FinishConversion() + Return + EndIf + + ; 启动第一批任务(最多 MAX_CONCURRENT 个) + _LaunchNextTasks() +EndFunc + +Func _LaunchNextTasks() + While UBound($g_aRunningTasks, 1) < $MAX_CONCURRENT And UBound($g_aPendingFiles) > 0 + Local $sFilePath = $g_aPendingFiles[0] + _ArrayDelete($g_aPendingFiles, 0) + + Local $sFileName = StringRegExpReplace($sFilePath, "^.*\\", "") ; 仅文件名 + Local $sBaseName = StringRegExpReplace($sFileName, "\.[^.\\]+$", "") + Local $sOutputDir = $g_sSourceDir & "\" & $sBaseName + + If DirCreate($sOutputDir) = 0 Then + _Log("[系统] ⚠️ 无法创建目录: " & $sOutputDir) + ContinueLoop + EndIf + + Local $sM3U8 = $sOutputDir & "\playlist.m3u8" + Local $sTS = $sOutputDir & "\segment_%05d.ts" + + Local $sCmd = 'ffmpeg -i "' & $sFilePath & '" ' & _ + '-c:v libx264 -crf 23 -preset fast -profile:v baseline -level 3.0 ' & _ + '-c:a aac -b:a 128k ' & _ + '-hls_time 2 ' & _ + '-hls_playlist_type vod ' & _ + '-hls_segment_filename "' & $sTS & '" ' & _ + '"' & $sM3U8 & '"' + + ; 启动进程并捕获合并输出 + Local $iPID = Run($sCmd, "", @SW_HIDE, $STDERR_MERGED) + If @error Then + _Log("[" & $sBaseName & "] ❌ 启动失败") + ContinueLoop + EndIf + + ; 记录任务 + Local $iIndex = UBound($g_aRunningTasks, 1) + ReDim $g_aRunningTasks[$iIndex + 1][4] + $g_aRunningTasks[$iIndex][0] = $iPID + $g_aRunningTasks[$iIndex][1] = $sBaseName + $g_aRunningTasks[$iIndex][2] = $sOutputDir + $g_aRunningTasks[$iIndex][3] = "" + + _Log("[" & $sBaseName & "] 🔄 开始转码...") + WEnd +EndFunc + +Func _PollRunningTasks() + If UBound($g_aRunningTasks, 1) = 0 Then + If UBound($g_aPendingFiles) = 0 Then + _FinishConversion() + EndIf + Return + EndIf + + Local $aToRemove[0] + + For $i = 0 To UBound($g_aRunningTasks, 1) - 1 + Local $iPID = $g_aRunningTasks[$i][0] + Local $sName = $g_aRunningTasks[$i][1] + + ; 读取新日志 + Local $sNewOutput = StdoutRead($iPID) + If $sNewOutput <> "" Then + ; 按行分割并加前缀 + Local $aLines = StringSplit(StringStripCR($sNewOutput), @LF, $STR_NOCOUNT) + For $j = 0 To UBound($aLines) - 1 + If $aLines[$j] <> "" Then + _Log("[" & $sName & "] " & $aLines[$j]) + EndIf + Next + EndIf + + ; 检查是否结束 + If Not ProcessExists($iPID) Then + Local $iExitCode = @extended ; 注意:Run 返回的 PID 在 ProcessExists 失败后,@extended 是退出码! + If $iExitCode = 0 Then + $g_iSuccess += 1 + _Log("[" & $sName & "] ✅ 成功完成") + Else + _Log("[" & $sName & "] ❌ 失败 (退出码: " & $iExitCode & ")") + EndIf + _ArrayAdd($aToRemove, $i) + EndIf + Next + + ; 移除已完成的任务(从后往前删) + For $i = UBound($aToRemove) - 1 To 0 Step -1 + Local $iIndex = $aToRemove[$i] + _ArrayDelete($g_aRunningTasks, $iIndex) + Next + + ; 启动新任务填补空缺 + If UBound($aToRemove) > 0 Then + _LaunchNextTasks() + EndIf +EndFunc + +Func _FinishConversion() + $g_bConverting = False + _Log(@CRLF & "🎉 所有转码任务完成!成功处理 " & $g_iSuccess & " 个视频。") + GUICtrlSetState($g_hBtnStart, $GUI_ENABLE) + GUICtrlSetState($g_hBtnSelect, $GUI_ENABLE) +EndFunc + +Func _KillAllRunningTasks() + If Not IsArray($g_aRunningTasks) Then Return + For $i = 0 To UBound($g_aRunningTasks, 1) - 1 + ProcessClose($g_aRunningTasks[$i][0]) + Next +EndFunc + +Func _Log($sText) + Local $sCurrent = GUICtrlRead($g_hLogEdit) + Local $sNew = $sCurrent & $sText & @CRLF + If StringLen($sNew) > 2000 Then + $sNew = StringRight($sNew, 2000) + EndIf + GUICtrlSetData($g_hLogEdit, $sNew) + GUICtrlSendMsg($g_hLogEdit, $EM_LINESCROLL, 0, GUICtrlSendMsg($g_hLogEdit, $EM_GETLINECOUNT, 0, 0)) +EndFunc + +Func _IsInArray($aArray, $sValue) + For $i = 0 To UBound($aArray) - 1 + If $aArray[$i] = $sValue Then Return True + Next + Return False +EndFunc \ No newline at end of file diff --git a/压缩包/au3脚本/视频转码.exe b/压缩包/au3脚本/视频转码.exe new file mode 100644 index 0000000000000000000000000000000000000000..8fde1e1774d25451cd815e6220fcd84d2f06c2c0 GIT binary patch literal 1038336 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 z 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�HCvlR$L^e|HH&N!M0vzUl^VR#^b$txR=bq#5zNb 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