UNPKG

@esotericsoftware/spine-pixi-v8

Version:
4 lines 943 kB
{ "version": 3, "sources": ["../../src/require-shim.ts", "../../src/assets/atlasLoader.ts", "../../src/SpineTexture.ts", "../../../spine-core/src/Utils.ts", "../../../spine-core/src/attachments/Attachment.ts", "../../../spine-core/src/attachments/Sequence.ts", "../../../spine-core/src/Animation.ts", "../../../spine-core/src/AnimationState.ts", "../../../spine-core/src/AnimationStateData.ts", "../../../spine-core/src/attachments/BoundingBoxAttachment.ts", "../../../spine-core/src/attachments/ClippingAttachment.ts", "../../../spine-core/src/Texture.ts", "../../../spine-core/src/TextureAtlas.ts", "../../../spine-core/src/attachments/MeshAttachment.ts", "../../../spine-core/src/attachments/PathAttachment.ts", "../../../spine-core/src/attachments/PointAttachment.ts", "../../../spine-core/src/attachments/RegionAttachment.ts", "../../../spine-core/src/AtlasAttachmentLoader.ts", "../../../spine-core/src/BoneData.ts", "../../../spine-core/src/Bone.ts", "../../../spine-core/src/ConstraintData.ts", "../../../spine-core/src/AssetManagerBase.ts", "../../../spine-core/src/Event.ts", "../../../spine-core/src/EventData.ts", "../../../spine-core/src/IkConstraint.ts", "../../../spine-core/src/IkConstraintData.ts", "../../../spine-core/src/PathConstraintData.ts", "../../../spine-core/src/PathConstraint.ts", "../../../spine-core/src/PhysicsConstraint.ts", "../../../spine-core/src/Slot.ts", "../../../spine-core/src/TransformConstraint.ts", "../../../spine-core/src/Skeleton.ts", "../../../spine-core/src/PhysicsConstraintData.ts", "../../../spine-core/src/SkeletonData.ts", "../../../spine-core/src/Skin.ts", "../../../spine-core/src/SlotData.ts", "../../../spine-core/src/TransformConstraintData.ts", "../../../spine-core/src/SkeletonBinary.ts", "../../../spine-core/src/SkeletonBounds.ts", "../../../spine-core/src/Triangulator.ts", "../../../spine-core/src/SkeletonClipping.ts", "../../../spine-core/src/SkeletonJson.ts", "../../../spine-core/src/polyfills.ts", "../../src/assets/skeletonLoader.ts", "../../src/darktint/DarkTintBatcher.ts", "../../src/darktint/DarkTintBatchGeometry.ts", "../../src/darktint/DarkTintShader.ts", "../../src/darktint/darkTintBit.ts", "../../src/SpinePipe.ts", "../../src/BatchableSpineSlot.ts", "../../src/Spine.ts", "../../src/SpineDebugRenderer.ts"], "sourcesContent": ["/** ****************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\ndeclare global {\n\tvar require: any;\n\tvar PIXI: any;\n}\n\nif (typeof window !== 'undefined' && window.PIXI) {\n\tconst prevRequire = window.require;\n\t(window as any).require = (x: string) => {\n\t\tif (prevRequire) return prevRequire(x);\n\t\telse if (x.startsWith(\"@pixi/\") || x.startsWith(\"pixi.js\")) return window.PIXI;\n\t};\n}\n\nexport { };\n", "/** ****************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport {\n\tcheckExtension,\n\tcopySearchParams,\n\tDOMAdapter,\n\textensions,\n\tExtensionType,\n\tLoaderParserPriority,\n\tpath,\n\tResolver,\n\tTextureSource\n} from 'pixi.js';\nimport { SpineTexture } from '../SpineTexture.js';\nimport { TextureAtlas } from '@esotericsoftware/spine-core';\n\nimport type { AssetExtension, Loader, ResolvedAsset, Texture, UnresolvedAsset } from 'pixi.js';\n\ntype RawAtlas = string;\n\nconst spineTextureAtlasLoader: AssetExtension<RawAtlas | TextureAtlas, ISpineAtlasMetadata> = {\n\textension: ExtensionType.Asset,\n\n\tresolver: {\n\t\ttest: (value: string): boolean => checkExtension(value, \".atlas\"),\n\t\tparse: (value: string): UnresolvedAsset => {\n\t\t\tconst split = value.split('.');\n\n\t\t\treturn {\n\t\t\t\tresolution: parseFloat(Resolver.RETINA_PREFIX?.exec(value)?.[1] ?? '1'),\n\t\t\t\tformat: split[split.length - 2],\n\t\t\t\tsrc: value,\n\t\t\t};\n\t\t},\n\t},\n\n\tloader: {\n\t\textension: {\n\t\t\ttype: ExtensionType.LoadParser,\n\t\t\tpriority: LoaderParserPriority.Normal,\n\t\t\tname: 'spineTextureAtlasLoader',\n\t\t},\n\n\t\ttest (url: string): boolean {\n\t\t\treturn checkExtension(url, '.atlas');\n\t\t},\n\n\t\tasync load (url: string): Promise<RawAtlas> {\n\t\t\tconst response = await DOMAdapter.get().fetch(url);\n\n\t\t\tconst txt = await response.text();\n\n\t\t\treturn txt;\n\t\t},\n\n\t\ttestParse (asset: unknown, options: ResolvedAsset): Promise<boolean> {\n\t\t\tconst isExtensionRight = checkExtension(options.src as string, '.atlas');\n\t\t\tconst isString = typeof asset === 'string';\n\n\t\t\treturn Promise.resolve(isExtensionRight && isString);\n\t\t},\n\n\t\tunload (atlas: TextureAtlas) {\n\t\t\tatlas.dispose();\n\t\t},\n\n\t\tasync parse (asset: RawAtlas, options: ResolvedAsset, loader: Loader): Promise<TextureAtlas> {\n\t\t\tconst metadata: ISpineAtlasMetadata = options.data || {};\n\t\t\tlet basePath = path.dirname(options.src as string);\n\n\t\t\tif (basePath && basePath.lastIndexOf('/') !== basePath.length - 1) {\n\t\t\t\tbasePath += '/';\n\t\t\t}\n\n\t\t\t// Retval is going to be a texture atlas. However we need to wait for it's callback to resolve this promise.\n\t\t\tconst retval = new TextureAtlas(asset);\n\n\t\t\t// If the user gave me only one texture, that one is assumed to be the \"first\" texture in the atlas\n\t\t\tif (metadata.images instanceof TextureSource || typeof metadata.images === 'string') {\n\t\t\t\tconst pixiTexture = metadata.images;\n\n\t\t\t\tmetadata.images = {} as Record<string, TextureSource | string>;\n\t\t\t\tmetadata.images[retval.pages[0].name] = pixiTexture;\n\t\t\t}\n\n\t\t\t// we will wait for all promises for the textures at the same time at the end.\n\t\t\tconst textureLoadingPromises: Promise<any>[] = [];\n\n\t\t\t// fill the pages\n\t\t\tfor (const page of retval.pages) {\n\t\t\t\tconst pageName = page.name;\n\t\t\t\tconst providedPage = metadata?.images ? metadata.images[pageName] : undefined;\n\n\t\t\t\tif (providedPage instanceof TextureSource) {\n\t\t\t\t\tpage.setTexture(SpineTexture.from(providedPage));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// eslint-disable-next-line max-len\n\t\t\t\t\tconst url: string = providedPage ?? path.normalize([...basePath.split(path.sep), pageName].join(path.sep));\n\n\t\t\t\t\tconst assetsToLoadIn = {\n\t\t\t\t\t\tsrc: copySearchParams(url, options.src as string),\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t...metadata.imageMetadata,\n\t\t\t\t\t\t\talphaMode: page.pma ? 'premultiplied-alpha' : 'premultiply-alpha-on-upload'\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tconst pixiPromise = loader.load<Texture>(assetsToLoadIn).then((texture) => {\n\t\t\t\t\t\tpage.setTexture(SpineTexture.from(texture.source));\n\t\t\t\t\t});\n\n\t\t\t\t\ttextureLoadingPromises.push(pixiPromise);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait Promise.all(textureLoadingPromises);\n\n\t\t\treturn retval;\n\t\t},\n\t},\n} as AssetExtension<RawAtlas | TextureAtlas, ISpineAtlasMetadata>;\n\nextensions.add(spineTextureAtlasLoader);\n\nexport interface ISpineAtlasMetadata {\n\t// If you are downloading an .atlas file, this metadata will go to the Texture loader\n\timageMetadata?: any;\n\t// If you already have atlas pages loaded as pixi textures\n\t// and want to use that to create the atlas, you can pass them here\n\timages?: TextureSource | string | Record<string, TextureSource | string>;\n}\n", "/** ****************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture as PixiTexture } from 'pixi.js';\nimport { BlendMode, Texture, TextureFilter, TextureWrap } from '@esotericsoftware/spine-core';\n\nimport type { BLEND_MODES, SCALE_MODE, TextureSource, WRAP_MODE } from 'pixi.js';\n\nexport class SpineTexture extends Texture {\n\tprivate static readonly textureMap: Map<TextureSource, SpineTexture> = new Map<TextureSource, SpineTexture>();\n\n\tpublic static from (texture: TextureSource): SpineTexture {\n\t\tif (SpineTexture.textureMap.has(texture)) {\n\t\t\treturn SpineTexture.textureMap.get(texture) as SpineTexture;\n\t\t}\n\n\t\treturn new SpineTexture(texture);\n\t}\n\n\tpublic readonly texture: PixiTexture;\n\n\tprivate constructor (image: TextureSource) {\n\t\t// Todo: maybe add error handling if you feed a video texture to spine?\n\t\tsuper(image.resource);\n\t\tthis.texture = PixiTexture.from(image);\n\t}\n\n\tpublic setFilters (minFilter: TextureFilter, magFilter: TextureFilter): void {\n\t\tconst style = this.texture.source.style;\n\n\t\tstyle.minFilter = SpineTexture.toPixiTextureFilter(minFilter);\n\t\tstyle.magFilter = SpineTexture.toPixiTextureFilter(magFilter);\n\t\tthis.texture.source.autoGenerateMipmaps = SpineTexture.toPixiMipMap(minFilter);\n\t\tthis.texture.source.updateMipmaps();\n\t}\n\n\tpublic setWraps (uWrap: TextureWrap, vWrap: TextureWrap): void {\n\t\tconst style = this.texture.source.style;\n\n\t\tstyle.addressModeU = SpineTexture.toPixiTextureWrap(uWrap);\n\t\tstyle.addressModeV = SpineTexture.toPixiTextureWrap(vWrap);\n\t}\n\n\tpublic dispose (): void {\n\t\t// I am not entirely sure about this...\n\t\tthis.texture.destroy();\n\t}\n\n\tprivate static toPixiMipMap (filter: TextureFilter): boolean {\n\t\tswitch (filter) {\n\t\t\tcase TextureFilter.Nearest:\n\t\t\tcase TextureFilter.Linear:\n\t\t\t\treturn false;\n\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\tcase TextureFilter.MipMapLinearLinear: // TextureFilter.MipMapLinearLinear == TextureFilter.MipMap\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\t\treturn true;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown texture filter: ${String(filter)}`);\n\t\t}\n\t}\n\n\tprivate static toPixiTextureFilter (filter: TextureFilter): SCALE_MODE {\n\t\tswitch (filter) {\n\t\t\tcase TextureFilter.Nearest:\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\t\treturn 'nearest';\n\n\t\t\tcase TextureFilter.Linear:\n\t\t\tcase TextureFilter.MipMapLinearLinear: // TextureFilter.MipMapLinearLinear == TextureFilter.MipMap\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\t\treturn 'linear';\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown texture filter: ${String(filter)}`);\n\t\t}\n\t}\n\n\tprivate static toPixiTextureWrap (wrap: TextureWrap): WRAP_MODE {\n\t\tswitch (wrap) {\n\t\t\tcase TextureWrap.ClampToEdge:\n\t\t\t\treturn 'clamp-to-edge';\n\n\t\t\tcase TextureWrap.MirroredRepeat:\n\t\t\t\treturn 'mirror-repeat';\n\n\t\t\tcase TextureWrap.Repeat:\n\t\t\t\treturn 'repeat';\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown texture wrap: ${String(wrap)}`);\n\t\t}\n\t}\n\n\tpublic static toPixiBlending (blend: BlendMode): BLEND_MODES {\n\t\tswitch (blend) {\n\t\t\tcase BlendMode.Normal:\n\t\t\t\treturn 'normal';\n\n\t\t\tcase BlendMode.Additive:\n\t\t\t\treturn 'add';\n\n\t\t\tcase BlendMode.Multiply:\n\t\t\t\treturn 'multiply';\n\n\t\t\tcase BlendMode.Screen:\n\t\t\t\treturn 'screen';\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown blendMode: ${String(blend)}`);\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Skeleton } from \"./Skeleton.js\";\nimport { MixBlend } from \"./Animation.js\";\n\nexport interface StringMap<T> {\n\t[key: string]: T;\n}\n\nexport class IntSet {\n\tarray = new Array<number | undefined>();\n\n\tadd (value: number): boolean {\n\t\tlet contains = this.contains(value);\n\t\tthis.array[value | 0] = value | 0;\n\t\treturn !contains;\n\t}\n\n\tcontains (value: number) {\n\t\treturn this.array[value | 0] != undefined;\n\t}\n\n\tremove (value: number) {\n\t\tthis.array[value | 0] = undefined;\n\t}\n\n\tclear () {\n\t\tthis.array.length = 0;\n\t}\n}\n\nexport class StringSet {\n\tentries: StringMap<boolean> = {};\n\tsize = 0;\n\n\tadd (value: string): boolean {\n\t\tlet contains = this.entries[value];\n\t\tthis.entries[value] = true;\n\t\tif (!contains) {\n\t\t\tthis.size++;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\taddAll (values: string[]): boolean {\n\t\tlet oldSize = this.size;\n\t\tfor (var i = 0, n = values.length; i < n; i++)\n\t\t\tthis.add(values[i]);\n\t\treturn oldSize != this.size;\n\t}\n\n\tcontains (value: string) {\n\t\treturn this.entries[value];\n\t}\n\n\tclear () {\n\t\tthis.entries = {};\n\t\tthis.size = 0;\n\t}\n}\n\nexport type NumberArrayLike = Array<number> | Float32Array;\nexport type IntArrayLike = Array<number> | Int16Array;\n\nexport interface Disposable {\n\tdispose (): void;\n}\n\nexport interface Restorable {\n\trestore (): void;\n}\n\nexport class Color {\n\tpublic static WHITE = new Color(1, 1, 1, 1);\n\tpublic static RED = new Color(1, 0, 0, 1);\n\tpublic static GREEN = new Color(0, 1, 0, 1);\n\tpublic static BLUE = new Color(0, 0, 1, 1);\n\tpublic static MAGENTA = new Color(1, 0, 1, 1);\n\n\tconstructor (public r: number = 0, public g: number = 0, public b: number = 0, public a: number = 0) {\n\t}\n\n\tset (r: number, g: number, b: number, a: number) {\n\t\tthis.r = r;\n\t\tthis.g = g;\n\t\tthis.b = b;\n\t\tthis.a = a;\n\t\treturn this.clamp();\n\t}\n\n\tsetFromColor (c: Color) {\n\t\tthis.r = c.r;\n\t\tthis.g = c.g;\n\t\tthis.b = c.b;\n\t\tthis.a = c.a;\n\t\treturn this;\n\t}\n\n\tsetFromString (hex: string) {\n\t\thex = hex.charAt(0) == '#' ? hex.substr(1) : hex;\n\t\tthis.r = parseInt(hex.substr(0, 2), 16) / 255;\n\t\tthis.g = parseInt(hex.substr(2, 2), 16) / 255;\n\t\tthis.b = parseInt(hex.substr(4, 2), 16) / 255;\n\t\tthis.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255;\n\t\treturn this;\n\t}\n\n\tadd (r: number, g: number, b: number, a: number) {\n\t\tthis.r += r;\n\t\tthis.g += g;\n\t\tthis.b += b;\n\t\tthis.a += a;\n\t\treturn this.clamp();\n\t}\n\n\tclamp () {\n\t\tif (this.r < 0) this.r = 0;\n\t\telse if (this.r > 1) this.r = 1;\n\n\t\tif (this.g < 0) this.g = 0;\n\t\telse if (this.g > 1) this.g = 1;\n\n\t\tif (this.b < 0) this.b = 0;\n\t\telse if (this.b > 1) this.b = 1;\n\n\t\tif (this.a < 0) this.a = 0;\n\t\telse if (this.a > 1) this.a = 1;\n\t\treturn this;\n\t}\n\n\tstatic rgba8888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0xff000000) >>> 24) / 255;\n\t\tcolor.g = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.b = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.a = ((value & 0x000000ff)) / 255;\n\t}\n\n\tstatic rgb888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.g = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.b = ((value & 0x000000ff)) / 255;\n\t}\n\n\ttoRgb888 () {\n\t\tconst hex = (x: number) => (\"0\" + (x * 255).toString(16)).slice(-2);\n\t\treturn Number(\"0x\" + hex(this.r) + hex(this.g) + hex(this.b));\n\t}\n\n\tstatic fromString (hex: string): Color {\n\t\treturn new Color().setFromString(hex);\n\t}\n}\n\nexport class MathUtils {\n\tstatic PI = 3.1415927;\n\tstatic PI2 = MathUtils.PI * 2;\n\tstatic invPI2 = 1 / MathUtils.PI2;\n\tstatic radiansToDegrees = 180 / MathUtils.PI;\n\tstatic radDeg = MathUtils.radiansToDegrees;\n\tstatic degreesToRadians = MathUtils.PI / 180;\n\tstatic degRad = MathUtils.degreesToRadians;\n\n\tstatic clamp (value: number, min: number, max: number) {\n\t\tif (value < min) return min;\n\t\tif (value > max) return max;\n\t\treturn value;\n\t}\n\n\tstatic cosDeg (degrees: number) {\n\t\treturn Math.cos(degrees * MathUtils.degRad);\n\t}\n\n\tstatic sinDeg (degrees: number) {\n\t\treturn Math.sin(degrees * MathUtils.degRad);\n\t}\n\n\tstatic atan2Deg (y: number, x: number) {\n\t\treturn Math.atan2(y, x) * MathUtils.degRad;\n\t}\n\n\tstatic signum (value: number): number {\n\t\treturn value > 0 ? 1 : value < 0 ? -1 : 0;\n\t}\n\n\tstatic toInt (x: number) {\n\t\treturn x > 0 ? Math.floor(x) : Math.ceil(x);\n\t}\n\n\tstatic cbrt (x: number) {\n\t\tlet y = Math.pow(Math.abs(x), 1 / 3);\n\t\treturn x < 0 ? -y : y;\n\t}\n\n\tstatic randomTriangular (min: number, max: number): number {\n\t\treturn MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);\n\t}\n\n\tstatic randomTriangularWith (min: number, max: number, mode: number): number {\n\t\tlet u = Math.random();\n\t\tlet d = max - min;\n\t\tif (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min));\n\t\treturn max - Math.sqrt((1 - u) * d * (max - mode));\n\t}\n\n\tstatic isPowerOfTwo (value: number) {\n\t\treturn value && (value & (value - 1)) === 0;\n\t}\n}\n\nexport abstract class Interpolation {\n\tprotected abstract applyInternal (a: number): number;\n\tapply (start: number, end: number, a: number): number {\n\t\treturn start + (end - start) * this.applyInternal(a);\n\t}\n}\n\nexport class Pow extends Interpolation {\n\tprotected power = 2;\n\n\tconstructor (power: number) {\n\t\tsuper();\n\t\tthis.power = power;\n\t}\n\n\tapplyInternal (a: number): number {\n\t\tif (a <= 0.5) return Math.pow(a * 2, this.power) / 2;\n\t\treturn Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;\n\t}\n}\n\nexport class PowOut extends Pow {\n\tconstructor (power: number) {\n\t\tsuper(power);\n\t}\n\n\tapplyInternal (a: number): number {\n\t\treturn Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;\n\t}\n}\n\nexport class Utils {\n\tstatic SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== \"undefined\";\n\n\tstatic arrayCopy<T> (source: ArrayLike<T>, sourceStart: number, dest: ArrayLike<T>, destStart: number, numElements: number) {\n\t\tfor (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {\n\t\t\tdest[j] = source[i];\n\t\t}\n\t}\n\n\tstatic arrayFill<T> (array: ArrayLike<T>, fromIndex: number, toIndex: number, value: T) {\n\t\tfor (let i = fromIndex; i < toIndex; i++)\n\t\t\tarray[i] = value;\n\t}\n\n\tstatic setArraySize<T> (array: Array<T>, size: number, value: any = 0): Array<T> {\n\t\tlet oldSize = array.length;\n\t\tif (oldSize == size) return array;\n\t\tarray.length = size;\n\t\tif (oldSize < size) {\n\t\t\tfor (let i = oldSize; i < size; i++) array[i] = value;\n\t\t}\n\t\treturn array;\n\t}\n\n\tstatic ensureArrayCapacity<T> (array: Array<T>, size: number, value: any = 0): Array<T> {\n\t\tif (array.length >= size) return array;\n\t\treturn Utils.setArraySize(array, size, value);\n\t}\n\n\tstatic newArray<T> (size: number, defaultValue: T): Array<T> {\n\t\tlet array = new Array<T>(size);\n\t\tfor (let i = 0; i < size; i++) array[i] = defaultValue;\n\t\treturn array;\n\t}\n\n\tstatic newFloatArray (size: number): NumberArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Float32Array(size)\n\t\telse {\n\t\t\tlet array = new Array<number>(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic newShortArray (size: number): IntArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Int16Array(size)\n\t\telse {\n\t\t\tlet array = new Array<number>(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic toFloatArray (array: Array<number>) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;\n\t}\n\n\tstatic toSinglePrecision (value: number) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;\n\t}\n\n\t// This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\tstatic webkit602BugfixHelper (alpha: number, blend: MixBlend) {\n\t}\n\n\tstatic contains<T> (array: Array<T>, element: T, identity = true) {\n\t\tfor (var i = 0; i < array.length; i++)\n\t\t\tif (array[i] == element) return true;\n\t\treturn false;\n\t}\n\n\tstatic enumValue (type: any, name: string) {\n\t\treturn type[name[0].toUpperCase() + name.slice(1)];\n\t}\n}\n\nexport class DebugUtils {\n\tstatic logBones (skeleton: Skeleton) {\n\t\tfor (let i = 0; i < skeleton.bones.length; i++) {\n\t\t\tlet bone = skeleton.bones[i];\n\t\t\tconsole.log(bone.data.name + \", \" + bone.a + \", \" + bone.b + \", \" + bone.c + \", \" + bone.d + \", \" + bone.worldX + \", \" + bone.worldY);\n\t\t}\n\t}\n}\n\nexport class Pool<T> {\n\tprivate items = new Array<T>();\n\tprivate instantiator: () => T;\n\n\tconstructor (instantiator: () => T) {\n\t\tthis.instantiator = instantiator;\n\t}\n\n\tobtain () {\n\t\treturn this.items.length > 0 ? this.items.pop()! : this.instantiator();\n\t}\n\n\tfree (item: T) {\n\t\tif ((item as any).reset) (item as any).reset();\n\t\tthis.items.push(item);\n\t}\n\n\tfreeAll (items: ArrayLike<T>) {\n\t\tfor (let i = 0; i < items.length; i++)\n\t\t\tthis.free(items[i]);\n\t}\n\n\tclear () {\n\t\tthis.items.length = 0;\n\t}\n}\n\nexport class Vector2 {\n\tconstructor (public x = 0, public y = 0) {\n\t}\n\n\tset (x: number, y: number): Vector2 {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t}\n\n\tlength () {\n\t\tlet x = this.x;\n\t\tlet y = this.y;\n\t\treturn Math.sqrt(x * x + y * y);\n\t}\n\n\tnormalize () {\n\t\tlet len = this.length();\n\t\tif (len != 0) {\n\t\t\tthis.x /= len;\n\t\t\tthis.y /= len;\n\t\t}\n\t\treturn this;\n\t}\n}\n\nexport class TimeKeeper {\n\tmaxDelta = 0.064;\n\tframesPerSecond = 0;\n\tdelta = 0;\n\ttotalTime = 0;\n\n\tprivate lastTime = Date.now() / 1000;\n\tprivate frameCount = 0;\n\tprivate frameTime = 0;\n\n\tupdate () {\n\t\tlet now = Date.now() / 1000;\n\t\tthis.delta = now - this.lastTime;\n\t\tthis.frameTime += this.delta;\n\t\tthis.totalTime += this.delta;\n\t\tif (this.delta > this.maxDelta) this.delta = this.maxDelta;\n\t\tthis.lastTime = now;\n\n\t\tthis.frameCount++;\n\t\tif (this.frameTime > 1) {\n\t\t\tthis.framesPerSecond = this.frameCount / this.frameTime;\n\t\t\tthis.frameTime = 0;\n\t\t\tthis.frameCount = 0;\n\t\t}\n\t}\n}\n\nexport interface ArrayLike<T> {\n\tlength: number;\n\t[n: number]: T;\n}\n\nexport class WindowedMean {\n\tvalues: Array<number>;\n\taddedValues = 0;\n\tlastValue = 0;\n\tmean = 0;\n\tdirty = true;\n\n\tconstructor (windowSize: number = 32) {\n\t\tthis.values = new Array<number>(windowSize);\n\t}\n\n\thasEnoughData () {\n\t\treturn this.addedValues >= this.values.length;\n\t}\n\n\taddValue (value: number) {\n\t\tif (this.addedValues < this.values.length) this.addedValues++;\n\t\tthis.values[this.lastValue++] = value;\n\t\tif (this.lastValue > this.values.length - 1) this.lastValue = 0;\n\t\tthis.dirty = true;\n\t}\n\n\tgetMean () {\n\t\tif (this.hasEnoughData()) {\n\t\t\tif (this.dirty) {\n\t\t\t\tlet mean = 0;\n\t\t\t\tfor (let i = 0; i < this.values.length; i++)\n\t\t\t\t\tmean += this.values[i];\n\t\t\t\tthis.mean = mean / this.values.length;\n\t\t\t\tthis.dirty = false;\n\t\t\t}\n\t\t\treturn this.mean;\n\t\t}\n\t\treturn 0;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Slot } from \"../Slot.js\";\nimport { NumberArrayLike, Utils } from \"../Utils.js\";\n\n/** The base class for all attachments. */\nexport abstract class Attachment {\n\tname: string;\n\n\tconstructor (name: string) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t}\n\n\tabstract copy (): Attachment;\n}\n\n/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's\n * {@link Slot#deform}. */\nexport abstract class VertexAttachment extends Attachment {\n\tprivate static nextID = 0;\n\n\t/** The unique ID for this attachment. */\n\tid = VertexAttachment.nextID++;\n\n\t/** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting\n\t * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null\n\t * if this attachment has no weights. */\n\tbones: Array<number> | null = null;\n\n\t/** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y`\n\t * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting\n\t * each vertex. */\n\tvertices: NumberArrayLike = [];\n\n\t/** The maximum number of world vertex values that can be output by\n\t * {@link #computeWorldVertices()} using the `count` parameter. */\n\tworldVerticesLength = 0;\n\n\t/** Timelines for the timeline attachment are also applied to this attachment.\n\t * May be null if no attachment-specific timelines should be applied. */\n\ttimelineAttachment: Attachment = this;\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\t/** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is\n\t * not empty, it is used to deform the vertices.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide.\n\t * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y.\n\t * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`.\n\t * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` *\n\t * `stride` / 2.\n\t * @param offset The `worldVertices` index to begin writing values.\n\t * @param stride The number of `worldVertices` entries between the value pairs written. */\n\tcomputeWorldVertices (slot: Slot, start: number, count: number, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tcount = offset + (count >> 1) * stride;\n\t\tlet skeleton = slot.bone.skeleton;\n\t\tlet deformArray = slot.deform;\n\t\tlet vertices = this.vertices;\n\t\tlet bones = this.bones;\n\t\tif (!bones) {\n\t\t\tif (deformArray.length > 0) vertices = deformArray;\n\t\t\tlet bone = slot.bone;\n\t\t\tlet x = bone.worldX;\n\t\t\tlet y = bone.worldY;\n\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\tfor (let v = start, w = offset; w < count; v += 2, w += stride) {\n\t\t\t\tlet vx = vertices[v], vy = vertices[v + 1];\n\t\t\t\tworldVertices[w] = vx * a + vy * b + x;\n\t\t\t\tworldVertices[w + 1] = vx * c + vy * d + y;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet v = 0, skip = 0;\n\t\tfor (let i = 0; i < start; i += 2) {\n\t\t\tlet n = bones[v];\n\t\t\tv += n + 1;\n\t\t\tskip += n;\n\t\t}\n\t\tlet skeletonBones = skeleton.bones;\n\t\tif (deformArray.length == 0) {\n\t\t\tfor (let w = offset, b = skip * 3; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t} else {\n\t\t\tlet deform = deformArray;\n\t\t\tfor (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3, f += 2) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Does not copy id (generated) or name (set on construction). **/\n\tcopyTo (attachment: VertexAttachment) {\n\t\tif (this.bones) {\n\t\t\tattachment.bones = new Array<number>(this.bones.length);\n\t\t\tUtils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length);\n\t\t} else\n\t\t\tattachment.bones = null;\n\n\t\tif (this.vertices) {\n\t\t\tattachment.vertices = Utils.newFloatArray(this.vertices.length);\n\t\t\tUtils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length);\n\t\t}\n\n\t\tattachment.worldVerticesLength = this.worldVerticesLength;\n\t\tattachment.timelineAttachment = this.timelineAttachment;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TextureRegion } from \"../Texture.js\";\nimport { Slot } from \"../Slot.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Utils } from \"../Utils.js\";\n\n\nexport class Sequence {\n\tprivate static _nextID = 0;\n\n\tid = Sequence.nextID();\n\tregions: TextureRegion[];\n\tstart = 0;\n\tdigits = 0;\n\t/** The index of the region to show for the setup pose. */\n\tsetupIndex = 0;\n\n\tconstructor (count: number) {\n\t\tthis.regions = new Array<TextureRegion>(count);\n\t}\n\n\tcopy (): Sequence {\n\t\tlet copy = new Sequence(this.regions.length);\n\t\tUtils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);\n\t\tcopy.start = this.start;\n\t\tcopy.digits = this.digits;\n\t\tcopy.setupIndex = this.setupIndex;\n\t\treturn copy;\n\t}\n\n\tapply (slot: Slot, attachment: HasTextureRegion) {\n\t\tlet index = slot.sequenceIndex;\n\t\tif (index == -1) index = this.setupIndex;\n\t\tif (index >= this.regions.length) index = this.regions.length - 1;\n\t\tlet region = this.regions[index];\n\t\tif (attachment.region != region) {\n\t\t\tattachment.region = region;\n\t\t\tattachment.updateRegion();\n\t\t}\n\t}\n\n\tgetPath (basePath: string, index: number): string {\n\t\tlet result = basePath;\n\t\tlet frame = (this.start + index).toString();\n\t\tfor (let i = this.digits - frame.length; i > 0; i--)\n\t\t\tresult += \"0\";\n\t\tresult += frame;\n\t\treturn result;\n\t}\n\n\tprivate static nextID (): number {\n\t\treturn Sequence._nextID++;\n\t}\n}\n\nexport enum SequenceMode {\n\thold = 0,\n\tonce = 1,\n\tloop = 2,\n\tpingpong = 3,\n\tonceReverse = 4,\n\tloopReverse = 5,\n\tpingpongReverse = 6\n}\n\nexport const SequenceModeValues = [\n\tSequenceMode.hold,\n\tSequenceMode.once,\n\tSequenceMode.loop,\n\tSequenceMode.pingpong,\n\tSequenceMode.onceReverse,\n\tSequenceMode.loopReverse,\n\tSequenceMode.pingpongReverse\n];\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { IkConstraint } from \"./IkConstraint.js\";\nimport { PathConstraint } from \"./PathConstraint.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { TransformConstraint } from \"./TransformConstraint.js\";\nimport { StringSet, Utils, MathUtils, NumberArrayLike } from \"./Utils.js\";\nimport { Event } from \"./Event.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { SequenceMode, SequenceModeValues } from \"./attachments/Sequence.js\";\nimport { PhysicsConstraint } from \"./PhysicsConstraint.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Inherit } from \"./BoneData.js\";\n\n/** A simple container for a list of timelines and a name. */\nexport class Animation {\n\t/** The animation's name, which is unique across all animations in the skeleton. */\n\tname: string;\n\ttimelines: Array<Timeline> = [];\n\ttimelineIds: StringSet = new StringSet();\n\n\t/** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */\n\tduration: number;\n\n\tconstructor (name: string, timelines: Array<Timeline>, duration: number) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t\tthis.setTimelines(timelines);\n\t\tthis.duration = duration;\n\t}\n\n\tsetTimelines (timelines: Array<Timeline>) {\n\t\tif (!timelines) throw new Error(\"timelines cannot be null.\");\n\t\tthis.timelines = timelines;\n\t\tthis.timelineIds.clear();\n\t\tfor (var i = 0; i < timelines.length; i++)\n\t\t\tthis.timelineIds.addAll(timelines[i].getPropertyIds());\n\t}\n\n\thasTimeline (ids: string[]): boolean {\n\t\tfor (let i = 0; i < ids.length; i++)\n\t\t\tif (this.timelineIds.contains(ids[i])) return true;\n\t\treturn false;\n\t}\n\n\t/** Applies all the animation's timelines to the specified skeleton.\n\t *\n\t * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}.\n\t * @param loop If true, the animation repeats after {@link #getDuration()}.\n\t * @param events May be null to ignore fired events. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\n\t\tif (loop && this.duration != 0) {\n\t\t\ttime %= this.duration;\n\t\t\tif (lastTime > 0) lastTime %= this.duration;\n\t\t}\n\n\t\tlet timelines = this.timelines;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\ttimelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);\n\t}\n}\n\n/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's `alpha`\n * < 1.\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixBlend {\n\t/** Transitions from the setup value to the timeline value (the current value is not used). Before the first key, the setup\n\t * value is set. */\n\tsetup,\n\t/** Transitions from the current value to the timeline value. Before the first key, transitions from the current value to\n\t * the setup value. Timelines which perform instant transitions, such as {@link DrawOrderTimeline} or\n\t * {@link AttachmentTimeline}, use the setup value before the first key.\n\t *\n\t * `first` is intended for the first animations applied, not for animations layered on top of those. */\n\tfirst,\n\t/** Transitions from the current value to the timeline value. No change is made before the first key (the current value is\n\t * kept until the first key).\n\t *\n\t * `replace` is intended for animations layered on top of others, not for the first animations applied. */\n\treplace,\n\t/** Transitions from the current value to the current value plus the timeline value. No change is made before the first key\n\t * (the current value is kept until the first key).\n\t *\n\t * `add` is intended for animations layered on top of others, not for the first animations applied. Properties\n\t * keyed by additive animations must be set manually or by another animation before applying the additive animations, else\n\t * the property values will increase continually. */\n\tadd\n}\n\n/** Indicates whether a timeline's `alpha` is mixing out over time toward 0 (the setup or current pose value) or\n * mixing in toward 1 (the timeline's value).\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixDirection {\n\tmixIn, mixOut\n}\n\nconst Property = {\n\trotate: 0,\n\tx: 1,\n\ty: 2,\n\tscaleX: 3,\n\tscaleY: 4,\n\tshearX: 5,\n\tshearY: 6,\n\tinherit: 7,\n\n\trgb: 8,\n\talpha: 9,\n\trgb2: 10,\n\n\tattachment: 11,\n\tdeform: 12,\n\n\tevent: 13,\n\tdrawOrder: 14,\n\n\tikConstraint: 15,\n\ttransformConstraint: 16,\n\n\tpathConstraintPosition: 17,\n\tpathConstraintSpacing: 18,\n\tpathConstraintMix: 19,\n\n\tphysicsConstraintInertia: 20,\n\tphysicsConstraintStrength: 21,\n\tphysicsConstraintDamping: 22,\n\tphysicsConstraintMass: 23,\n\tphysicsConstraintWind: 24,\n\tphysicsConstraintGravity: 25,\n\tphysicsConstraintMix: 26,\n\tphysicsConstraintReset: 27,\n\n\tsequence: 28,\n}\n\n/** The interface for all timelines. */\nexport abstract class Timeline {\n\tpropertyIds: string[];\n\tframes: NumberArrayLike;\n\n\tconstructor (frameCount: number, propertyIds: string[]) {\n\t\tthis.propertyIds = propertyIds;\n\t\tthis.frames = Utils.newFloatArray(frameCount * this.getFrameEntries());\n\t}\n\n\tgetPropertyIds () {\n\t\treturn this.propertyIds;\n\t}\n\n\tgetFrameEntries (): number {\n\t\treturn 1;\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length / this.getFrameEntries();\n\t}\n\n\tgetDuration (): number {\n\t\treturn this.frames[this.frames.length - this.getFrameEntries()];\n\t}\n\n\tabstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event> | null, alpha: number, blend: MixBlend, direction: MixDirection): void;\n\n\tstatic search1 (frames: NumberArrayLike, time: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = 1; i < n; i++)\n\t\t\tif (frames[i] > time) return i - 1;\n\t\treturn n - 1;\n\t}\n\n\tstatic search (frames: NumberArrayLike, time: number, step: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = step; i < n; i += step)\n\t\t\tif (frames[i] > time) return i - step;\n\t\treturn n - step;\n\t}\n}\n\nexport interface BoneTimeline {\n\t/** The index of the bone in {@link Skeleton#bones} that will be changed. */\n\tboneIndex: number;\n}\n\nexport interface SlotTimeline {\n\t/** The index of the slot in {@link Skeleton#slots} that will be changed. */\n\tslotIndex: number;\n}\n\n/** The base class for timelines that use interpolation between key frame values. */\nexport abstract class CurveTimeline extends Timeline {\n\tprotected curves: NumberArrayLike; // type, x, y, ...\n\n\tconstructor (frameCount: number, bezierCount: number, propertyIds: string[]) {\n\t\tsuper(frameCount, propertyIds);\n\t\tthis.curves = Utils.newFloatArray(frameCount + bezierCount * 18/*BEZIER_SIZE*/);\n\t\tthis.curves[frameCount - 1] = 1/*STEPPED*/;\n\t}\n\n\t/** Sets the specified key frame to linear interpolation. */\n\tsetLinear (frame: number) {\n\t\tthis.curves[frame] = 0/*LINEAR*/;\n\t}\n\n\t/** Sets the specified key frame to stepped interpolation. */\n\tsetStepped (frame: number) {\n\t\tthis.curves[frame] = 1/*STEPPED*/;\n\t}\n\n\t/** Shrinks the storage for Bezier curves, for use when <code>bezierCount</code> (specified in the constructor) was larger\n\t * than the actual number of Bezier curves. */\n\tshrink (bezierCount: number) {\n\t\tlet size = this.getFrameCount() + bezierCount * 18/*BEZIER_SIZE*/;\n\t\tif (this.curves.length > size) {\n\t\t\tlet newCurves = Utils.newFloatArray(size);\n\t\t\tUtils.arrayCopy(this.curves, 0, newCurves, 0, size);\n\t\t\tthis.curves = newCurves;\n\t\t}\n\t}\n\n\t/** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than\n\t * one curve per frame.\n\t * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and <code>bezierCount - 1</code> (specified\n\t * in the constructor), inclusive.\n\t * @param frame Betwee