@pixi-spine/runtime-3.8
Version:
Pixi runtime for spine 3.8 models
1 lines • 84.7 kB
Source Map (JSON)
{"version":3,"file":"SkeletonJson.mjs","sources":["../../src/core/SkeletonJson.ts"],"sourcesContent":["import type { Attachment, AttachmentLoader, MeshAttachment, VertexAttachment } from './attachments';\nimport { Event } from './Event';\nimport { SkeletonData } from './SkeletonData';\nimport { SlotData } from './SlotData';\nimport { BoneData } from './BoneData';\nimport { IkConstraintData } from './IkConstraintData';\nimport { TransformConstraintData } from './TransformConstraintData';\nimport { PathConstraintData, SpacingMode } from './PathConstraintData';\nimport { Skin } from './Skin';\nimport { EventData } from './EventData';\nimport {\n Animation,\n AttachmentTimeline,\n ColorTimeline,\n CurveTimeline,\n DeformTimeline,\n DrawOrderTimeline,\n EventTimeline,\n IkConstraintTimeline,\n PathConstraintMixTimeline,\n PathConstraintPositionTimeline,\n PathConstraintSpacingTimeline,\n RotateTimeline,\n ScaleTimeline,\n ShearTimeline,\n Timeline,\n TransformConstraintTimeline,\n TranslateTimeline,\n TwoColorTimeline,\n} from './Animation';\nimport { ArrayLike, Color, PositionMode, RotateMode, TransformMode, Utils, settings } from '@pixi-spine/base';\nimport { BLEND_MODES } from '@pixi/core';\n\n/**\n * @public\n */\nexport class SkeletonJson {\n attachmentLoader: AttachmentLoader;\n scale = 1;\n private linkedMeshes = new Array<LinkedMesh>();\n\n constructor(attachmentLoader: AttachmentLoader) {\n this.attachmentLoader = attachmentLoader;\n }\n\n readSkeletonData(json: string | any): SkeletonData {\n const scale = this.scale;\n const skeletonData = new SkeletonData();\n const root = typeof json === 'string' ? JSON.parse(json) : json;\n\n // Skeleton\n const skeletonMap = root.skeleton;\n\n if (skeletonMap != null) {\n skeletonData.hash = skeletonMap.hash;\n skeletonData.version = skeletonMap.spine;\n if (skeletonData.version.substr(0, 3) !== '3.8') {\n const error = `Spine 3.8 loader cant load version ${skeletonMap.spine}. Please configure your pixi-spine bundle`;\n\n console.error(error);\n }\n if (skeletonData.version === '3.8.75') {\n const error = `Unsupported skeleton data, 3.8.75 is deprecated, please export with a newer version of Spine.`;\n\n console.error(error);\n }\n skeletonData.x = skeletonMap.x;\n skeletonData.y = skeletonMap.y;\n skeletonData.width = skeletonMap.width;\n skeletonData.height = skeletonMap.height;\n skeletonData.fps = skeletonMap.fps;\n skeletonData.imagesPath = skeletonMap.images;\n }\n\n // Bones\n if (root.bones) {\n for (let i = 0; i < root.bones.length; i++) {\n const boneMap = root.bones[i];\n\n let parent: BoneData = null;\n const parentName: string = this.getValue(boneMap, 'parent', null);\n\n if (parentName != null) {\n parent = skeletonData.findBone(parentName);\n if (parent == null) throw new Error(`Parent bone not found: ${parentName}`);\n }\n const data = new BoneData(skeletonData.bones.length, boneMap.name, parent);\n\n data.length = this.getValue(boneMap, 'length', 0) * scale;\n data.x = this.getValue(boneMap, 'x', 0) * scale;\n data.y = this.getValue(boneMap, 'y', 0) * scale;\n data.rotation = this.getValue(boneMap, 'rotation', 0);\n data.scaleX = this.getValue(boneMap, 'scaleX', 1);\n data.scaleY = this.getValue(boneMap, 'scaleY', 1);\n data.shearX = this.getValue(boneMap, 'shearX', 0);\n data.shearY = this.getValue(boneMap, 'shearY', 0);\n data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, 'transform', 'normal'));\n data.skinRequired = this.getValue(boneMap, 'skin', false);\n\n skeletonData.bones.push(data);\n }\n }\n\n // Slots.\n if (root.slots) {\n for (let i = 0; i < root.slots.length; i++) {\n const slotMap = root.slots[i];\n const slotName: string = slotMap.name;\n const boneName: string = slotMap.bone;\n const boneData = skeletonData.findBone(boneName);\n\n if (boneData == null) throw new Error(`Slot bone not found: ${boneName}`);\n const data = new SlotData(skeletonData.slots.length, slotName, boneData);\n\n const color: string = this.getValue(slotMap, 'color', null);\n\n if (color != null) data.color.setFromString(color);\n\n const dark: string = this.getValue(slotMap, 'dark', null);\n\n if (dark != null) {\n data.darkColor = new Color(1, 1, 1, 1);\n data.darkColor.setFromString(dark);\n }\n\n data.attachmentName = this.getValue(slotMap, 'attachment', null);\n data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, 'blend', 'normal'));\n skeletonData.slots.push(data);\n }\n }\n\n // IK constraints\n if (root.ik) {\n for (let i = 0; i < root.ik.length; i++) {\n const constraintMap = root.ik[i];\n const data = new IkConstraintData(constraintMap.name);\n\n data.order = this.getValue(constraintMap, 'order', 0);\n data.skinRequired = this.getValue(constraintMap, 'skin', false);\n\n for (let j = 0; j < constraintMap.bones.length; j++) {\n const boneName = constraintMap.bones[j];\n const bone = skeletonData.findBone(boneName);\n\n if (bone == null) throw new Error(`IK bone not found: ${boneName}`);\n data.bones.push(bone);\n }\n\n const targetName: string = constraintMap.target;\n\n data.target = skeletonData.findBone(targetName);\n if (data.target == null) throw new Error(`IK target bone not found: ${targetName}`);\n\n data.mix = this.getValue(constraintMap, 'mix', 1);\n data.softness = this.getValue(constraintMap, 'softness', 0) * scale;\n data.bendDirection = this.getValue(constraintMap, 'bendPositive', true) ? 1 : -1;\n data.compress = this.getValue(constraintMap, 'compress', false);\n data.stretch = this.getValue(constraintMap, 'stretch', false);\n data.uniform = this.getValue(constraintMap, 'uniform', false);\n\n skeletonData.ikConstraints.push(data);\n }\n }\n\n // Transform constraints.\n if (root.transform) {\n for (let i = 0; i < root.transform.length; i++) {\n const constraintMap = root.transform[i];\n const data = new TransformConstraintData(constraintMap.name);\n\n data.order = this.getValue(constraintMap, 'order', 0);\n data.skinRequired = this.getValue(constraintMap, 'skin', false);\n\n for (let j = 0; j < constraintMap.bones.length; j++) {\n const boneName = constraintMap.bones[j];\n const bone = skeletonData.findBone(boneName);\n\n if (bone == null) throw new Error(`Transform constraint bone not found: ${boneName}`);\n data.bones.push(bone);\n }\n\n const targetName: string = constraintMap.target;\n\n data.target = skeletonData.findBone(targetName);\n if (data.target == null) throw new Error(`Transform constraint target bone not found: ${targetName}`);\n\n data.local = this.getValue(constraintMap, 'local', false);\n data.relative = this.getValue(constraintMap, 'relative', false);\n data.offsetRotation = this.getValue(constraintMap, 'rotation', 0);\n data.offsetX = this.getValue(constraintMap, 'x', 0) * scale;\n data.offsetY = this.getValue(constraintMap, 'y', 0) * scale;\n data.offsetScaleX = this.getValue(constraintMap, 'scaleX', 0);\n data.offsetScaleY = this.getValue(constraintMap, 'scaleY', 0);\n data.offsetShearY = this.getValue(constraintMap, 'shearY', 0);\n\n data.rotateMix = this.getValue(constraintMap, 'rotateMix', 1);\n data.translateMix = this.getValue(constraintMap, 'translateMix', 1);\n data.scaleMix = this.getValue(constraintMap, 'scaleMix', 1);\n data.shearMix = this.getValue(constraintMap, 'shearMix', 1);\n\n skeletonData.transformConstraints.push(data);\n }\n }\n\n // Path constraints.\n if (root.path) {\n for (let i = 0; i < root.path.length; i++) {\n const constraintMap = root.path[i];\n const data = new PathConstraintData(constraintMap.name);\n\n data.order = this.getValue(constraintMap, 'order', 0);\n data.skinRequired = this.getValue(constraintMap, 'skin', false);\n\n for (let j = 0; j < constraintMap.bones.length; j++) {\n const boneName = constraintMap.bones[j];\n const bone = skeletonData.findBone(boneName);\n\n if (bone == null) throw new Error(`Transform constraint bone not found: ${boneName}`);\n data.bones.push(bone);\n }\n\n const targetName: string = constraintMap.target;\n\n data.target = skeletonData.findSlot(targetName);\n if (data.target == null) throw new Error(`Path target slot not found: ${targetName}`);\n\n data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, 'positionMode', 'percent'));\n data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, 'spacingMode', 'length'));\n data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, 'rotateMode', 'tangent'));\n data.offsetRotation = this.getValue(constraintMap, 'rotation', 0);\n data.position = this.getValue(constraintMap, 'position', 0);\n if (data.positionMode == PositionMode.Fixed) data.position *= scale;\n data.spacing = this.getValue(constraintMap, 'spacing', 0);\n if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;\n data.rotateMix = this.getValue(constraintMap, 'rotateMix', 1);\n data.translateMix = this.getValue(constraintMap, 'translateMix', 1);\n\n skeletonData.pathConstraints.push(data);\n }\n }\n\n // Skins.\n if (root.skins) {\n for (let i = 0; i < root.skins.length; i++) {\n const skinMap = root.skins[i];\n const skin = new Skin(skinMap.name);\n\n if (skinMap.bones) {\n for (let ii = 0; ii < skinMap.bones.length; ii++) {\n const bone = skeletonData.findBone(skinMap.bones[ii]);\n\n if (bone == null) throw new Error(`Skin bone not found: ${skinMap.bones[i]}`);\n skin.bones.push(bone);\n }\n }\n\n if (skinMap.ik) {\n for (let ii = 0; ii < skinMap.ik.length; ii++) {\n const constraint = skeletonData.findIkConstraint(skinMap.ik[ii]);\n\n if (constraint == null) throw new Error(`Skin IK constraint not found: ${skinMap.ik[i]}`);\n skin.constraints.push(constraint);\n }\n }\n\n if (skinMap.transform) {\n for (let ii = 0; ii < skinMap.transform.length; ii++) {\n const constraint = skeletonData.findTransformConstraint(skinMap.transform[ii]);\n\n if (constraint == null) throw new Error(`Skin transform constraint not found: ${skinMap.transform[i]}`);\n skin.constraints.push(constraint);\n }\n }\n\n if (skinMap.path) {\n for (let ii = 0; ii < skinMap.path.length; ii++) {\n const constraint = skeletonData.findPathConstraint(skinMap.path[ii]);\n\n if (constraint == null) throw new Error(`Skin path constraint not found: ${skinMap.path[i]}`);\n skin.constraints.push(constraint);\n }\n }\n\n for (const slotName in skinMap.attachments) {\n const slot = skeletonData.findSlot(slotName);\n\n if (slot == null) throw new Error(`Slot not found: ${slotName}`);\n const slotMap = skinMap.attachments[slotName];\n\n for (const entryName in slotMap) {\n const attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData);\n\n if (attachment != null) skin.setAttachment(slot.index, entryName, attachment);\n }\n }\n skeletonData.skins.push(skin);\n if (skin.name == 'default') skeletonData.defaultSkin = skin;\n }\n }\n\n // Linked meshes.\n for (let i = 0, n = this.linkedMeshes.length; i < n; i++) {\n const linkedMesh = this.linkedMeshes[i];\n const skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);\n\n if (skin == null) throw new Error(`Skin not found: ${linkedMesh.skin}`);\n const parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);\n\n if (parent == null) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);\n linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? <VertexAttachment>parent : <VertexAttachment>linkedMesh.mesh;\n linkedMesh.mesh.setParentMesh(<MeshAttachment>parent);\n // linkedMesh.mesh.updateUVs();\n }\n this.linkedMeshes.length = 0;\n\n // Events.\n if (root.events) {\n for (const eventName in root.events) {\n const eventMap = root.events[eventName];\n const data = new EventData(eventName);\n\n data.intValue = this.getValue(eventMap, 'int', 0);\n data.floatValue = this.getValue(eventMap, 'float', 0);\n data.stringValue = this.getValue(eventMap, 'string', '');\n data.audioPath = this.getValue(eventMap, 'audio', null);\n if (data.audioPath != null) {\n data.volume = this.getValue(eventMap, 'volume', 1);\n data.balance = this.getValue(eventMap, 'balance', 0);\n }\n skeletonData.events.push(data);\n }\n }\n\n // Animations.\n if (root.animations) {\n for (const animationName in root.animations) {\n const animationMap = root.animations[animationName];\n\n this.readAnimation(animationMap, animationName, skeletonData);\n }\n }\n\n return skeletonData;\n }\n\n readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment {\n const scale = this.scale;\n\n name = this.getValue(map, 'name', name);\n\n const type = this.getValue(map, 'type', 'region');\n\n switch (type) {\n case 'region': {\n const path = this.getValue(map, 'path', name);\n const region = this.attachmentLoader.newRegionAttachment(skin, name, path);\n\n if (region == null) return null;\n region.path = path;\n region.x = this.getValue(map, 'x', 0) * scale;\n region.y = this.getValue(map, 'y', 0) * scale;\n region.scaleX = this.getValue(map, 'scaleX', 1);\n region.scaleY = this.getValue(map, 'scaleY', 1);\n region.rotation = this.getValue(map, 'rotation', 0);\n region.width = map.width * scale;\n region.height = map.height * scale;\n\n const color: string = this.getValue(map, 'color', null);\n\n if (color != null) region.color.setFromString(color);\n\n // region.updateOffset();\n return region;\n }\n case 'boundingbox': {\n const box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);\n\n if (box == null) return null;\n this.readVertices(map, box, map.vertexCount << 1);\n const color: string = this.getValue(map, 'color', null);\n\n if (color != null) box.color.setFromString(color);\n\n return box;\n }\n case 'mesh':\n case 'linkedmesh': {\n const path = this.getValue(map, 'path', name);\n const mesh = this.attachmentLoader.newMeshAttachment(skin, name, path);\n\n if (mesh == null) return null;\n mesh.path = path;\n\n const color = this.getValue(map, 'color', null);\n\n if (color != null) mesh.color.setFromString(color);\n\n mesh.width = this.getValue(map, 'width', 0) * scale;\n mesh.height = this.getValue(map, 'height', 0) * scale;\n\n const parent: string = this.getValue(map, 'parent', null);\n\n if (parent != null) {\n this.linkedMeshes.push(new LinkedMesh(mesh, <string>this.getValue(map, 'skin', null), slotIndex, parent, this.getValue(map, 'deform', true)));\n\n return mesh;\n }\n\n const uvs: Array<number> = map.uvs;\n\n this.readVertices(map, mesh, uvs.length);\n mesh.triangles = map.triangles;\n mesh.regionUVs = new Float32Array(uvs);\n // mesh.updateUVs();\n\n mesh.edges = this.getValue(map, 'edges', null);\n mesh.hullLength = this.getValue(map, 'hull', 0) * 2;\n\n return mesh;\n }\n case 'path': {\n const path = this.attachmentLoader.newPathAttachment(skin, name);\n\n if (path == null) return null;\n path.closed = this.getValue(map, 'closed', false);\n path.constantSpeed = this.getValue(map, 'constantSpeed', true);\n\n const vertexCount = map.vertexCount;\n\n this.readVertices(map, path, vertexCount << 1);\n\n const lengths: Array<number> = Utils.newArray(vertexCount / 3, 0);\n\n for (let i = 0; i < map.lengths.length; i++) lengths[i] = map.lengths[i] * scale;\n path.lengths = lengths;\n\n const color: string = this.getValue(map, 'color', null);\n\n if (color != null) path.color.setFromString(color);\n\n return path;\n }\n case 'point': {\n const point = this.attachmentLoader.newPointAttachment(skin, name);\n\n if (point == null) return null;\n point.x = this.getValue(map, 'x', 0) * scale;\n point.y = this.getValue(map, 'y', 0) * scale;\n point.rotation = this.getValue(map, 'rotation', 0);\n\n const color = this.getValue(map, 'color', null);\n\n if (color != null) point.color.setFromString(color);\n\n return point;\n }\n case 'clipping': {\n const clip = this.attachmentLoader.newClippingAttachment(skin, name);\n\n if (clip == null) return null;\n\n const end = this.getValue(map, 'end', null);\n\n if (end != null) {\n const slot = skeletonData.findSlot(end);\n\n if (slot == null) throw new Error(`Clipping end slot not found: ${end}`);\n clip.endSlot = slot;\n }\n\n const vertexCount = map.vertexCount;\n\n this.readVertices(map, clip, vertexCount << 1);\n\n const color: string = this.getValue(map, 'color', null);\n\n if (color != null) clip.color.setFromString(color);\n\n return clip;\n }\n }\n\n return null;\n }\n\n readVertices(map: any, attachment: VertexAttachment, verticesLength: number) {\n const scale = this.scale;\n\n attachment.worldVerticesLength = verticesLength;\n const vertices: Array<number> = map.vertices;\n\n if (verticesLength == vertices.length) {\n const scaledVertices = Utils.toFloatArray(vertices);\n\n if (scale != 1) {\n for (let i = 0, n = vertices.length; i < n; i++) scaledVertices[i] *= scale;\n }\n attachment.vertices = scaledVertices;\n\n return;\n }\n const weights = new Array<number>();\n const bones = new Array<number>();\n\n for (let i = 0, n = vertices.length; i < n; ) {\n const boneCount = vertices[i++];\n\n bones.push(boneCount);\n for (let nn = i + boneCount * 4; i < nn; i += 4) {\n bones.push(vertices[i]);\n weights.push(vertices[i + 1] * scale);\n weights.push(vertices[i + 2] * scale);\n weights.push(vertices[i + 3]);\n }\n }\n attachment.bones = bones;\n attachment.vertices = Utils.toFloatArray(weights);\n }\n\n readAnimation(map: any, name: string, skeletonData: SkeletonData) {\n const scale = this.scale;\n const timelines = new Array<Timeline>();\n let duration = 0;\n\n // Slot timelines.\n if (map.slots) {\n for (const slotName in map.slots) {\n const slotMap = map.slots[slotName];\n const slotIndex = skeletonData.findSlotIndex(slotName);\n\n if (slotIndex == -1) throw new Error(`Slot not found: ${slotName}`);\n for (const timelineName in slotMap) {\n const timelineMap = slotMap[timelineName];\n\n if (timelineName == 'attachment') {\n const timeline = new AttachmentTimeline(timelineMap.length);\n\n timeline.slotIndex = slotIndex;\n\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n\n timeline.setFrame(frameIndex++, this.getValue(valueMap, 'time', 0), valueMap.name);\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);\n } else if (timelineName == 'color') {\n const timeline = new ColorTimeline(timelineMap.length);\n\n timeline.slotIndex = slotIndex;\n\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n const color = new Color();\n\n color.setFromString(valueMap.color || 'ffffffff');\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), color.r, color.g, color.b, color.a);\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * ColorTimeline.ENTRIES]);\n } else if (timelineName == 'twoColor') {\n const timeline = new TwoColorTimeline(timelineMap.length);\n\n timeline.slotIndex = slotIndex;\n\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n const light = new Color();\n const dark = new Color();\n\n light.setFromString(valueMap.light);\n dark.setFromString(valueMap.dark);\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * TwoColorTimeline.ENTRIES]);\n } else throw new Error(`Invalid timeline type for a slot: ${timelineName} (${slotName})`);\n }\n }\n }\n\n // Bone timelines.\n if (map.bones) {\n for (const boneName in map.bones) {\n const boneMap = map.bones[boneName];\n const boneIndex = skeletonData.findBoneIndex(boneName);\n\n if (boneIndex == -1) throw new Error(`Bone not found: ${boneName}`);\n for (const timelineName in boneMap) {\n const timelineMap = boneMap[timelineName];\n\n if (timelineName === 'rotate') {\n const timeline = new RotateTimeline(timelineMap.length);\n\n timeline.boneIndex = boneIndex;\n\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), this.getValue(valueMap, 'angle', 0));\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * RotateTimeline.ENTRIES]);\n } else if (timelineName === 'translate' || timelineName === 'scale' || timelineName === 'shear') {\n let timeline: TranslateTimeline = null;\n let timelineScale = 1;\n let defaultValue = 0;\n\n if (timelineName === 'scale') {\n timeline = new ScaleTimeline(timelineMap.length);\n defaultValue = 1;\n } else if (timelineName === 'shear') timeline = new ShearTimeline(timelineMap.length);\n else {\n timeline = new TranslateTimeline(timelineMap.length);\n timelineScale = scale;\n }\n timeline.boneIndex = boneIndex;\n\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n const x = this.getValue(valueMap, 'x', defaultValue);\n const y = this.getValue(valueMap, 'y', defaultValue);\n\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), x * timelineScale, y * timelineScale);\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * TranslateTimeline.ENTRIES]);\n } else throw new Error(`Invalid timeline type for a bone: ${timelineName} (${boneName})`);\n }\n }\n }\n\n // IK constraint timelines.\n if (map.ik) {\n for (const constraintName in map.ik) {\n const constraintMap = map.ik[constraintName];\n const constraint = skeletonData.findIkConstraint(constraintName);\n const timeline = new IkConstraintTimeline(constraintMap.length);\n\n timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint);\n let frameIndex = 0;\n\n for (let i = 0; i < constraintMap.length; i++) {\n const valueMap = constraintMap[i];\n\n timeline.setFrame(\n frameIndex,\n this.getValue(valueMap, 'time', 0),\n this.getValue(valueMap, 'mix', 1),\n this.getValue(valueMap, 'softness', 0) * scale,\n this.getValue(valueMap, 'bendPositive', true) ? 1 : -1,\n this.getValue(valueMap, 'compress', false),\n this.getValue(valueMap, 'stretch', false)\n );\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * IkConstraintTimeline.ENTRIES]);\n }\n }\n\n // Transform constraint timelines.\n if (map.transform) {\n for (const constraintName in map.transform) {\n const constraintMap = map.transform[constraintName];\n const constraint = skeletonData.findTransformConstraint(constraintName);\n const timeline = new TransformConstraintTimeline(constraintMap.length);\n\n timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint);\n let frameIndex = 0;\n\n for (let i = 0; i < constraintMap.length; i++) {\n const valueMap = constraintMap[i];\n\n timeline.setFrame(\n frameIndex,\n this.getValue(valueMap, 'time', 0),\n this.getValue(valueMap, 'rotateMix', 1),\n this.getValue(valueMap, 'translateMix', 1),\n this.getValue(valueMap, 'scaleMix', 1),\n this.getValue(valueMap, 'shearMix', 1)\n );\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * TransformConstraintTimeline.ENTRIES]);\n }\n }\n\n // Path constraint timelines.\n if (map.path) {\n for (const constraintName in map.path) {\n const constraintMap = map.path[constraintName];\n const index = skeletonData.findPathConstraintIndex(constraintName);\n\n if (index == -1) throw new Error(`Path constraint not found: ${constraintName}`);\n const data = skeletonData.pathConstraints[index];\n\n for (const timelineName in constraintMap) {\n const timelineMap = constraintMap[timelineName];\n\n if (timelineName === 'position' || timelineName === 'spacing') {\n let timeline: PathConstraintPositionTimeline = null;\n let timelineScale = 1;\n\n if (timelineName === 'spacing') {\n timeline = new PathConstraintSpacingTimeline(timelineMap.length);\n if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) timelineScale = scale;\n } else {\n timeline = new PathConstraintPositionTimeline(timelineMap.length);\n if (data.positionMode == PositionMode.Fixed) timelineScale = scale;\n }\n timeline.pathConstraintIndex = index;\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), this.getValue(valueMap, timelineName, 0) * timelineScale);\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * PathConstraintPositionTimeline.ENTRIES]);\n } else if (timelineName === 'mix') {\n const timeline = new PathConstraintMixTimeline(timelineMap.length);\n\n timeline.pathConstraintIndex = index;\n let frameIndex = 0;\n\n for (let i = 0; i < timelineMap.length; i++) {\n const valueMap = timelineMap[i];\n\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), this.getValue(valueMap, 'rotateMix', 1), this.getValue(valueMap, 'translateMix', 1));\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * PathConstraintMixTimeline.ENTRIES]);\n }\n }\n }\n }\n\n // Deform timelines.\n if (map.deform) {\n for (const deformName in map.deform) {\n const deformMap = map.deform[deformName];\n const skin = skeletonData.findSkin(deformName);\n\n if (skin == null) {\n if (settings.FAIL_ON_NON_EXISTING_SKIN) {\n throw new Error(`Skin not found: ${deformName}`);\n } else {\n continue;\n }\n }\n for (const slotName in deformMap) {\n const slotMap = deformMap[slotName];\n const slotIndex = skeletonData.findSlotIndex(slotName);\n\n if (slotIndex == -1) throw new Error(`Slot not found: ${slotMap.name}`);\n for (const timelineName in slotMap) {\n const timelineMap = slotMap[timelineName];\n const attachment = <VertexAttachment>skin.getAttachment(slotIndex, timelineName);\n\n if (attachment == null) throw new Error(`Deform attachment not found: ${timelineMap.name}`);\n const weighted = attachment.bones != null;\n const vertices = attachment.vertices;\n const deformLength = weighted ? (vertices.length / 3) * 2 : vertices.length;\n\n const timeline = new DeformTimeline(timelineMap.length);\n\n timeline.slotIndex = slotIndex;\n timeline.attachment = attachment;\n\n let frameIndex = 0;\n\n for (let j = 0; j < timelineMap.length; j++) {\n const valueMap = timelineMap[j];\n let deform: ArrayLike<number>;\n const verticesValue: Array<Number> = this.getValue(valueMap, 'vertices', null);\n\n if (verticesValue == null) deform = weighted ? Utils.newFloatArray(deformLength) : vertices;\n else {\n deform = Utils.newFloatArray(deformLength);\n const start = <number>this.getValue(valueMap, 'offset', 0);\n\n Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);\n if (scale != 1) {\n for (let i = start, n = i + verticesValue.length; i < n; i++) deform[i] *= scale;\n }\n if (!weighted) {\n for (let i = 0; i < deformLength; i++) deform[i] += vertices[i];\n }\n }\n\n timeline.setFrame(frameIndex, this.getValue(valueMap, 'time', 0), deform);\n this.readCurve(valueMap, timeline, frameIndex);\n frameIndex++;\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);\n }\n }\n }\n }\n\n // Draw order timeline.\n let drawOrderNode = map.drawOrder;\n\n if (drawOrderNode == null) drawOrderNode = map.draworder;\n if (drawOrderNode != null) {\n const timeline = new DrawOrderTimeline(drawOrderNode.length);\n const slotCount = skeletonData.slots.length;\n let frameIndex = 0;\n\n for (let j = 0; j < drawOrderNode.length; j++) {\n const drawOrderMap = drawOrderNode[j];\n let drawOrder: Array<number> = null;\n const offsets = this.getValue(drawOrderMap, 'offsets', null);\n\n if (offsets != null) {\n drawOrder = Utils.newArray<number>(slotCount, -1);\n const unchanged = Utils.newArray<number>(slotCount - offsets.length, 0);\n let originalIndex = 0;\n let unchangedIndex = 0;\n\n for (let i = 0; i < offsets.length; i++) {\n const offsetMap = offsets[i];\n const slotIndex = skeletonData.findSlotIndex(offsetMap.slot);\n\n if (slotIndex == -1) throw new Error(`Slot not found: ${offsetMap.slot}`);\n // Collect unchanged items.\n while (originalIndex != slotIndex) unchanged[unchangedIndex++] = originalIndex++;\n // Set changed items.\n drawOrder[originalIndex + offsetMap.offset] = originalIndex++;\n }\n // Collect remaining unchanged items.\n while (originalIndex < slotCount) unchanged[unchangedIndex++] = originalIndex++;\n // Fill in unchanged items.\n for (let i = slotCount - 1; i >= 0; i--) if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];\n }\n timeline.setFrame(frameIndex++, this.getValue(drawOrderMap, 'time', 0), drawOrder);\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);\n }\n\n // Event timeline.\n if (map.events) {\n const timeline = new EventTimeline(map.events.length);\n let frameIndex = 0;\n\n for (let i = 0; i < map.events.length; i++) {\n const eventMap = map.events[i];\n const eventData = skeletonData.findEvent(eventMap.name);\n\n if (eventData == null) throw new Error(`Event not found: ${eventMap.name}`);\n const event = new Event(Utils.toSinglePrecision(this.getValue(eventMap, 'time', 0)), eventData);\n\n event.intValue = this.getValue(eventMap, 'int', eventData.intValue);\n event.floatValue = this.getValue(eventMap, 'float', eventData.floatValue);\n event.stringValue = this.getValue(eventMap, 'string', eventData.stringValue);\n if (event.data.audioPath != null) {\n event.volume = this.getValue(eventMap, 'volume', 1);\n event.balance = this.getValue(eventMap, 'balance', 0);\n }\n timeline.setFrame(frameIndex++, event);\n }\n timelines.push(timeline);\n duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);\n }\n\n if (isNaN(duration)) {\n throw new Error('Error while parsing animation, duration is NaN');\n }\n\n skeletonData.animations.push(new Animation(name, timelines, duration));\n }\n\n readCurve(map: any, timeline: CurveTimeline, frameIndex: number) {\n if (!map.hasOwnProperty('curve')) return;\n if (map.curve === 'stepped') timeline.setStepped(frameIndex);\n else {\n const curve: number = map.curve;\n\n timeline.setCurve(frameIndex, curve, this.getValue(map, 'c2', 0), this.getValue(map, 'c3', 1), this.getValue(map, 'c4', 1));\n }\n }\n\n getValue(map: any, prop: string, defaultValue: any) {\n return map[prop] !== undefined ? map[prop] : defaultValue;\n }\n\n static blendModeFromString(str: string) {\n str = str.toLowerCase();\n if (str == 'normal') return BLEND_MODES.NORMAL;\n if (str == 'additive') return BLEND_MODES.ADD;\n if (str == 'multiply') return BLEND_MODES.MULTIPLY;\n if (str == 'screen') return BLEND_MODES.SCREEN;\n throw new Error(`Unknown blend mode: ${str}`);\n }\n\n static positionModeFromString(str: string) {\n str = str.toLowerCase();\n if (str == 'fixed') return PositionMode.Fixed;\n if (str == 'percent') return PositionMode.Percent;\n throw new Error(`Unknown position mode: ${str}`);\n }\n\n static spacingModeFromString(str: string) {\n str = str.toLowerCase();\n if (str == 'length') return SpacingMode.Length;\n if (str == 'fixed') return SpacingMode.Fixed;\n if (str == 'percent') return SpacingMode.Percent;\n throw new Error(`Unknown position mode: ${str}`);\n }\n\n static rotateModeFromString(str: string) {\n str = str.toLowerCase();\n if (str == 'tangent') return RotateMode.Tangent;\n if (str == 'chain') return RotateMode.Chain;\n if (str == 'chainscale') return RotateMode.ChainScale;\n throw new Error(`Unknown rotate mode: ${str}`);\n }\n\n static transformModeFromString(str: string) {\n str = str.toLowerCase();\n if (str == 'normal') return TransformMode.Normal;\n if (str == 'onlytranslation') return TransformMode.OnlyTranslation;\n if (str == 'norotationorreflection') return TransformMode.NoRotationOrReflection;\n if (str == 'noscale') return TransformMode.NoScale;\n if (str == 'noscaleorreflection') return TransformMode.NoScaleOrReflection;\n throw new Error(`Unknown transform mode: ${str}`);\n }\n}\n\nclass LinkedMesh {\n parent: string;\n skin: string;\n slotIndex: number;\n mesh: MeshAttachment;\n inheritDeform: boolean;\n\n constructor(mesh: MeshAttachment, skin: string, slotIndex: number, parent: string, inheritDeform: boolean) {\n this.mesh = mesh;\n this.skin = skin;\n this.slotIndex = slotIndex;\n this.parent = parent;\n this.inheritDeform = inheritDeform;\n }\n}\n"],"names":[],"mappings":"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