[lua] SkeletonJson 4.0 port, clean up.

This commit is contained in:
Nathan Sweet 2021-06-03 21:55:17 -04:00
parent 7df74c2fa4
commit 3c0a43687b
18 changed files with 2258 additions and 2263 deletions

File diff suppressed because it is too large Load Diff

View File

@ -159,7 +159,7 @@ function EventQueue:drain ()
end
self:clear()
self.drainDisabled = false;
self.drainDisabled = false
end
function EventQueue:clear ()
@ -326,7 +326,7 @@ function AnimationState:updateMixingFrom (to, delta)
from.trackTime = from.trackTime + delta * from.timeScale
to.mixTime = to.mixTime + delta
return false;
return false
end
function AnimationState:apply (skeleton)
@ -388,7 +388,7 @@ function AnimationState:apply (skeleton)
end
end
self:queueEvents(current, animationTime)
self.events = {};
self.events = {}
current.nextAnimationLast = animationTime
current.nextTrackLast = current.trackTime
end
@ -400,7 +400,7 @@ function AnimationState:apply (skeleton)
-- subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or
-- the time is before the first key).
local setupState = self.unkeyedState + SETUP
local slots = skeleton.slots;
local slots = skeleton.slots
for _, slot in ipairs(slots) do
if slot.attachmentState == setupState then
local attachmentName = slot.data.attachmentName
@ -411,7 +411,7 @@ function AnimationState:apply (skeleton)
end
end
end
self.unkeyedState = self.unkeyedState + 2; -- Increasing after each use avoids the need to reset attachmentState for every slot.
self.unkeyedState = self.unkeyedState + 2 -- Increasing after each use avoids the need to reset attachmentState for every slot.
queue:drain()
@ -453,11 +453,11 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
local firstFrame = #from.timelinesRotation == 0
local timelinesRotation = from.timelinesRotation
from.totalAlpha = 0;
from.totalAlpha = 0
for i,timeline in ipairs(timelines) do
local skipSubsequent = false;
local direction = MixDirection.out;
local skipSubsequent = false
local direction = MixDirection.out
local timelineBlend = MixBlend.setup
local alpha = 0
if timelineMode[i] == SUBSEQUENT then
@ -498,7 +498,7 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
if (to.mixDuration > 0) then
self:queueEvents(from, animationTime)
end
self.events = {};
self.events = {}
from.nextAnimationLast = animationTime
from.nextTrackLast = from.trackTime
@ -506,20 +506,20 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
end
function AnimationState:applyAttachmentTimeline(timeline, skeleton, time, blend, attachments)
local slot = skeleton.slots[timeline.slotIndex];
local slot = skeleton.slots[timeline.slotIndex]
if slot.bone.active == false then return end
local frames = timeline.frames
if time < frames[0] then -- Time is before first frame.
if blend == MixBlend.setup or blend == MixBlend.first then
self:setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
self:setAttachment(skeleton, slot, slot.data.attachmentName, attachments)
end
else
local frameIndex = 0
if (time >= frames[zlen(frames) - 1]) then -- Time is after last frame.
frameIndex = zlen(frames) - 1;
frameIndex = zlen(frames) - 1
else
frameIndex = Animation.binarySearch(frames, time, 1) - 1;
frameIndex = Animation.binarySearch(frames, time, 1) - 1
end
self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
end
@ -665,7 +665,7 @@ function AnimationState:clearTracks ()
local queue = self.queue
local tracks = self.tracks
local oldDrainDisabled = queue.drainDisabled
queue.drainDisabled = true;
queue.drainDisabled = true
local numTracks = getNumTracks(tracks)
local i = 0
while i <= numTracks do
@ -673,7 +673,7 @@ function AnimationState:clearTracks ()
end
tracks = {}
queue.drainDisabled = oldDrainDisabled
queue:drain();
queue:drain()
end
function AnimationState:clearTrack (trackIndex)
@ -686,7 +686,7 @@ function AnimationState:clearTrack (trackIndex)
self:disposeNext(current)
local entry = current;
local entry = current
while (true) do
local from = entry.mixingFrom
if from == nil then break end
@ -717,7 +717,7 @@ function AnimationState:setCurrent (index, current, interrupt)
current.interruptAlpha = current.interruptAlpha * math_min(1, from.mixTime / from.mixDuration)
end
from.timelinesRotation = {};
from.timelinesRotation = {}
end
queue:start(current)
@ -731,7 +731,7 @@ end
function AnimationState:setAnimation (trackIndex, animation, loop)
if not animation then error("animation cannot be null.") end
local interrupt = true;
local interrupt = true
local current = self:expandToIndex(trackIndex)
local queue = self.queue
local tracks = self.tracks
@ -743,7 +743,7 @@ function AnimationState:setAnimation (trackIndex, animation, loop)
queue:_end(current)
self:disposeNext(current)
current = current.mixingFrom
interrupt = false;
interrupt = false
else
self:disposeNext(current)
end

View File

@ -40,13 +40,12 @@ local math_pi = math.pi
local TransformMode = require "spine-lua.TransformMode"
function math.sign(x)
if x<0 then
if x < 0 then
return -1
elseif x>0 then
elseif x > 0 then
return 1
else
return 0
end
return 0
end
local math_sign = math.sign
@ -96,8 +95,8 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
self.ashearY = shearY
self.appliedValid = true
local sx = self.skeleton.scaleX;
local sy = self.skeleton.scaleY;
local sx = self.skeleton.scaleX
local sy = self.skeleton.scaleY
local parent = self.parent
if parent == nil then
@ -132,7 +131,7 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
self.b = pa * lb + pb * ld
self.c = pc * la + pd * lc
self.d = pc * lb + pd * ld
return;
return
elseif transformMode == TransformMode.onlyTranslation then
local rotationY = rotation + 90 + shearY
self.a = math_cos(math_rad(rotation + shearX)) * scaleX
@ -148,11 +147,11 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
pc = pc / self.skeleton.scaleY
pb = pc * s
pd = pa * s
prx = math_deg(math_atan2(pc, pa));
prx = math_deg(math_atan2(pc, pa))
else
pa = 0;
pc = 0;
prx = 90 - math_deg(math_atan2(pd, pb));
pa = 0
pc = 0
prx = 90 - math_deg(math_atan2(pd, pb))
end
local rx = rotation + shearX - prx
local ry = rotation + shearY - prx + 90
@ -181,10 +180,10 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
local r = math_pi / 2 + math_atan2(zc, za)
local zb = math_cos(r) * s
local zd = math_sin(r) * s
local la = math_cos(math_rad(shearX)) * scaleX;
local lb = math_cos(math_rad(90 + shearY)) * scaleY;
local lc = math_sin(math_rad(shearX)) * scaleX;
local ld = math_sin(math_rad(90 + shearY)) * scaleY;
local la = math_cos(math_rad(shearX)) * scaleX
local lb = math_cos(math_rad(90 + shearY)) * scaleY
local lc = math_sin(math_rad(shearX)) * scaleX
local ld = math_sin(math_rad(90 + shearY)) * scaleY
self.a = za * la + zb * lc
self.b = za * lb + zb * ld
self.c = zc * la + zd * lc

View File

@ -47,7 +47,8 @@ function BoneData.new (index, name, parent)
shearX = 0, shearY = 0,
inheritRotation = true,
inheritScale = true,
skinRequired = false
skinRequired = false,
color = nil
}
return self

View File

@ -1,61 +0,0 @@
-------------------------------------------------------------------------------
-- Spine Runtimes License Agreement
-- Last updated January 1, 2020. Replaces all prior versions.
--
-- Copyright (c) 2013-2020, Esoteric Software LLC
--
-- Integration of the Spine Runtimes into software or otherwise creating
-- derivative works of the Spine Runtimes is permitted under the terms and
-- conditions of Section 2 of the Spine Editor License Agreement:
-- http://esotericsoftware.com/spine-editor-license
--
-- Otherwise, it is permitted to integrate the Spine Runtimes into software
-- or otherwise create derivative works of the Spine Runtimes (collectively,
-- "Products"), provided that each user of the Products must obtain their own
-- Spine Editor license and redistribution of the Products in any form must
-- include this license and copyright notice.
--
-- THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
-- BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
local AttachmentType = require "spine-lua.AttachmentType"
local BoundingBoxAttachment = {}
function BoundingBoxAttachment.new (name)
if not name then error("name cannot be nil", 2) end
local self = {
name = name,
type = AttachmentType.boundingbox,
vertices = {}
}
function self:computeWorldVertices (x, y, bone, worldVertices)
x = x + bone.worldX
y = y + bone.worldY
local m00 = bone.m00
local m01 = bone.m01
local m10 = bone.m10
local m11 = bone.m11
local vertices = self.vertices
local count = #vertices
for i = 1, count, 2 do
local px = vertices[i]
local py = vertices[i + 1]
worldVertices[i] = px * m00 + py * m01 + x
worldVertices[i + 1] = px * m10 + py * m11 + y
end
end
return self
end
return BoundingBoxAttachment

View File

@ -102,12 +102,12 @@ function IkConstraint:apply1 (bone, targetX, targetY, compress, stretch, uniform
tx = targetX - bone.worldX
ty = targetY - bone.worldY
elseif bone.data.transformMode == TransformMode.noRotationOrReflection then
local s = math_abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
local sa = pa / bone.skeleton.scaleX;
local sc = pc / bone.skeleton.scaleY;
pb = -sc * s * bone.skeleton.scaleX;
pd = sa * s * bone.skeleton.scaleY;
rotationIK = rotationIK + math_deg(math_atan2(sc, sa));
local s = math_abs(pa * pd - pb * pc) / (pa * pa + pc * pc)
local sa = pa / bone.skeleton.scaleX
local sc = pc / bone.skeleton.scaleY
pb = -sc * s * bone.skeleton.scaleX
pd = sa * s * bone.skeleton.scaleY
rotationIK = rotationIK + math_deg(math_atan2(sc, sa))
local x = targetX - p.worldX
@ -255,13 +255,13 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
b = psy * l2
local aa = a * a
local bb = b * b
local ta = math_atan2(ty, tx);
local ta = math_atan2(ty, tx)
c = bb * l1 * l1 + aa * dd - aa * bb
local c1 = -2 * bb * l1
local c2 = bb - aa
d = c1 * c1 - 4 * c2 * c
if d >= 0 then
local q = math_sqrt(d);
local q = math_sqrt(d)
if (c1 < 0) then q = -q end
q = -(c1 + q) / 2
local r0 = q / c2
@ -279,7 +279,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
local minAngle = math_pi
local minX = l1 - a
local minDist = minX * minX
local minY = 0;
local minY = 0
local maxAngle = 0
local maxX = l1 + a
local maxDist = maxX * maxX
@ -328,7 +328,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
elseif a2 < -180 then
a2 = a2 + 360
end
child:updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
child:updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY)
end
return IkConstraint

View File

@ -1,93 +0,0 @@
-------------------------------------------------------------------------------
-- Spine Runtimes License Agreement
-- Last updated January 1, 2020. Replaces all prior versions.
--
-- Copyright (c) 2013-2020, Esoteric Software LLC
--
-- Integration of the Spine Runtimes into software or otherwise creating
-- derivative works of the Spine Runtimes is permitted under the terms and
-- conditions of Section 2 of the Spine Editor License Agreement:
-- http://esotericsoftware.com/spine-editor-license
--
-- Otherwise, it is permitted to integrate the Spine Runtimes into software
-- or otherwise create derivative works of the Spine Runtimes (collectively,
-- "Products"), provided that each user of the Products must obtain their own
-- Spine Editor license and redistribution of the Products in any form must
-- include this license and copyright notice.
--
-- THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
-- BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
local AttachmentType = require "spine-lua.AttachmentType"
local MeshAttachment = {}
function MeshAttachment.new (name)
if not name then error("name cannot be nil", 2) end
local self = {
name = name,
type = AttachmentType.mesh,
vertices = nil,
uvs = nil,
regionUVs = nil,
triangles = nil,
hullLength = 0,
r = 1, g = 1, b = 1, a = 1,
path = nil,
rendererObject = nil,
regionU = 0, regionV = 0, regionU2 = 1, regionV2 = 1, regionRotate = false,
regionOffsetX = 0, regionOffsetY = 0,
regionWidth = 0, regionHeight = 0,
regionOriginalWidth = 0, regionOriginalHeight = 0,
edges = nil,
width = 0, height = 0
}
function self:updateUVs ()
local width, height = self.regionU2 - self.regionU, self.regionV2 - self.regionV
local n = #self.regionUVs
if not self.uvs or #self.uvs ~= n then
self.uvs = {}
end
if self.regionRotate then
for i = 1, n, 2 do
self.uvs[i] = self.regionU + self.regionUVs[i + 1] * width
self.uvs[i + 1] = self.regionV + height - self.regionUVs[i] * height
end
else
for i = 1, n, 2 do
self.uvs[i] = self.regionU + self.regionUVs[i] * width
self.uvs[i + 1] = self.regionV + self.regionUVs[i + 1] * height
end
end
end
function self:computeWorldVertices (x, y, slot, worldVertices)
local bone = slot.bone
x,y=slot.bone.skeleton.x,slot.bone.skeleton.y
x = x + bone.worldX
y = y + bone.worldY
local m00, m01, m10, m11 = bone.m00, bone.m01, bone.m10, bone.m11
local vertices = self.vertices
local verticesCount = #vertices
if slot.deform and #slot.deform == verticesCount then vertices = slot.deform end
for i = 1, verticesCount, 2 do
local vx = vertices[i]
local vy = vertices[i + 1]
worldVertices[i] = vx * m00 + vy * m01 + x
worldVertices[i + 1] = vx * m10 + vy * m11 + y
end
end
return self
end
return MeshAttachment

View File

@ -99,7 +99,7 @@ function PathConstraint:update ()
local rotate = rotateMix > 0
if not translate and not rotate then return end
local data = self.data;
local data = self.data
local percentSpacing = data.spacingMode == PathConstraintData.SpacingMode.percent
local rotateMode = data.rotateMode
local tangents = rotateMode == PathConstraintData.RotateMode.tangent
@ -117,7 +117,7 @@ function PathConstraint:update ()
local i = 0
local n = spacesCount - 1
while i < n do
local bone = bones[i + 1];
local bone = bones[i + 1]
local setupLength = bone.data.length
if setupLength < PathConstraint.epsilon then
if scale then lengths[i + 1] = 0 end
@ -157,12 +157,12 @@ function PathConstraint:update ()
local boneX = positions[1]
local boneY = positions[2]
local offsetRotation = data.offsetRotation
local tip = false;
local tip = false
if offsetRotation == 0 then
tip = rotateMode == PathConstraintData.RotateMode.chain
else
tip = false;
local p = self.target.bone;
tip = false
local p = self.target.bone
if p.a * p.d - p.b * p.c > 0 then
offsetRotation = offsetRotation * utils.degRad
else
@ -210,8 +210,8 @@ function PathConstraint:update ()
cos = math_cos(r)
sin = math_sin(r)
local length = bone.data.length
boneX = boneX + (length * (cos * a - sin * c) - dx) * rotateMix;
boneY = boneY + (length * (sin * a + cos * c) - dy) * rotateMix;
boneX = boneX + (length * (cos * a - sin * c) - dx) * rotateMix
boneY = boneY + (length * (sin * a + cos * c) - dy) * rotateMix
else
r = r + offsetRotation
end
@ -249,7 +249,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
if not path.constantSpeed then
local lengths = path.lengths
if closed then curveCount = curveCount - 1 else curveCount = curveCount - 2 end
local pathLength = lengths[curveCount + 1];
local pathLength = lengths[curveCount + 1]
if percentPosition then position = position * pathLength end
if percentSpacing then
i = 1
@ -258,12 +258,12 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
i = i + 1
end
end
world = utils.setArraySize(self.world, 8);
world = utils.setArraySize(self.world, 8)
i = 0
local o = 0
local curve = 0
while i < spacesCount do
local space = spaces[i + 1];
local space = spaces[i + 1]
position = position + space
local p = position
@ -331,14 +331,14 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
world[verticesLength - 1 + 1] = world[1 + 1]
else
curveCount = curveCount - 1
verticesLength = verticesLength - 4;
verticesLength = verticesLength - 4
world = utils.setArraySize(self.world, verticesLength)
path:computeWorldVertices(target, 2, verticesLength, world, 0, 2)
end
-- Curve lengths.
local curves = utils.setArraySize(self.curves, curveCount)
local pathLength = 0;
local pathLength = 0
local x1 = world[0 + 1]
local y1 = world[1 + 1]
local cx1 = 0
@ -392,7 +392,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
if percentPosition then
position = position * pathLength
else
position = position * pathLength / path.lengths[curveCount];
position = position * pathLength / path.lengths[curveCount]
end
if percentSpacing then
i = 1
@ -496,7 +496,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
local prev = segments[segment - 1 + 1]
p = segment + (p - prev) / (length - prev)
end
break;
break
end
segment = segment + 1
end
@ -536,7 +536,7 @@ function PathConstraint:addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2,
out[o + 1] = x1
out[o + 2] = y1
out[o + 3] = math_atan2(cy1 - y1, cx1 - x1)
return;
return
end
local tt = p * p
local ttt = tt * p

View File

@ -1,100 +0,0 @@
-------------------------------------------------------------------------------
-- Spine Runtimes License Agreement
-- Last updated January 1, 2020. Replaces all prior versions.
--
-- Copyright (c) 2013-2020, Esoteric Software LLC
--
-- Integration of the Spine Runtimes into software or otherwise creating
-- derivative works of the Spine Runtimes is permitted under the terms and
-- conditions of Section 2 of the Spine Editor License Agreement:
-- http://esotericsoftware.com/spine-editor-license
--
-- Otherwise, it is permitted to integrate the Spine Runtimes into software
-- or otherwise create derivative works of the Spine Runtimes (collectively,
-- "Products"), provided that each user of the Products must obtain their own
-- Spine Editor license and redistribution of the Products in any form must
-- include this license and copyright notice.
--
-- THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
-- BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
local AttachmentType = require "spine-lua.AttachmentType"
local RegionAttachment = {}
function RegionAttachment.new (name)
if not name then error("name cannot be nil", 2) end
local self = {
name = name,
type = AttachmentType.region,
x = 0, y = 0,
rotation = 0,
scaleX = 1, scaleY = 1,
width = 0, height = 0,
offset = {},
uvs = {},
r = 1, g = 1, b = 1, a = 1,
path = nil,
rendererObject = nil,
regionOffsetX = 0, regionOffsetY = 0,
regionWidth = 0, regionHeight = 0,
regionOriginalWidth = 0, regionOriginalHeight = 0
}
function self:updateOffset ()
local regionScaleX = self.width / self.regionOriginalWidth * self.scaleX
local regionScaleY = self.height / self.regionOriginalHeight * self.scaleY
local localX = -self.width / 2 * self.scaleX + self.regionOffsetX * regionScaleX
local localY = -self.height / 2 * self.scaleY + self.regionOffsetY * regionScaleY
local localX2 = localX + self.regionWidth * regionScaleX
local localY2 = localY + self.regionHeight * regionScaleY
local radians = self.rotation * math.pi / 180
local cos = math.cos(radians)
local sin = math.sin(radians)
local localXCos = localX * cos + self.x
local localXSin = localX * sin
local localYCos = localY * cos + self.y
local localYSin = localY * sin
local localX2Cos = localX2 * cos + self.x
local localX2Sin = localX2 * sin
local localY2Cos = localY2 * cos + self.y
local localY2Sin = localY2 * sin
local offset = self.offset
offset[0] = localXCos - localYSin -- X1
offset[1] = localYCos + localXSin -- Y1
offset[2] = localXCos - localY2Sin -- X2
offset[3] = localY2Cos + localXSin -- Y2
offset[4] = localX2Cos - localY2Sin -- X3
offset[5] = localY2Cos + localX2Sin -- Y3
offset[6] = localX2Cos - localYSin -- X4
offset[7] = localYCos + localX2Sin -- Y4
end
function self:computeWorldVertices (x, y, bone, worldVertices)
x = x + bone.worldX
y = y + bone.worldY
local m00, m01, m10, m11 = bone.m00, bone.m01, bone.m10, bone.m11
local offset = self.offset
local vertices = self.vertices;
vertices[0] = offset[0] * m00 + offset[1] * m01 + x
vertices[1] = offset[0] * m10 + offset[1] * m11 + y
vertices[2] = offset[2] * m00 + offset[3] * m01 + x
vertices[3] = offset[2] * m10 + offset[3] * m11 + y
vertices[4] = offset[4] * m00 + offset[5] * m01 + x
vertices[5] = offset[4] * m10 + offset[5] * m11 + y
vertices[6] = offset[6] * m00 + offset[7] * m01 + x
vertices[7] = offset[6] * m10 + offset[7] * m11 + y
end
return self
end
return RegionAttachment

View File

@ -460,7 +460,7 @@ function Skeleton:setSkinByReference(newSkin)
end
function Skeleton:getAttachment (slotName, attachmentName)
return self:getAttachmentByIndex(self.data.slotNameIndices[slotName], attachmentName)
return self:getAttachmentByIndex(self.data.nameToSlot[slotName].index, attachmentName)
end
function Skeleton:getAttachmentByIndex (slotIndex, attachmentName)
@ -520,7 +520,7 @@ end
function Skeleton:getBounds(offset, size)
if not offset then error("offset cannot be null.", 2) end
if not size then error("size cannot be null.", 2) end
local drawOrder = self.drawOrder;
local drawOrder = self.drawOrder
local minX = 99999999
local minY = 99999999
local maxX = -99999999

View File

@ -118,7 +118,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
local u2 = uvs[vertexOffset]
local v2 = uvs[vertexOffset + 1]
vertexOffset = (triangles[i + 2] - 1) * 2 + 1;
vertexOffset = (triangles[i + 2] - 1) * 2 + 1
local x3 = vertices[vertexOffset]
local y3 = vertices[vertexOffset + 1]
local u3 = uvs[vertexOffset]
@ -135,7 +135,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
local d1 = x3 - x2
local d2 = x1 - x3
local d4 = y3 - y1
local d = 1 / (d0 * d2 + d1 * (y1 - y3));
local d = 1 / (d0 * d2 + d1 * (y1 - y3))
local clipOutputCount = clipOutputLength / 2
local clipOutputItems = clipOutput
@ -193,7 +193,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
clippedTrianglesItems[s] = index
clippedTrianglesItems[s + 1] = index + 1
clippedTrianglesItems[s + 2] = index + 2
index = index + 3;
index = index + 3
break
end
p = p + 1
@ -246,7 +246,7 @@ function SkeletonClipping:clip(x1, y1, x2, y2, x3, y3, clippingArea, output)
local inputX2 = inputVertices[ii + 2]
local inputY2 = inputVertices[ii + 3]
local side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0
local continue = false;
local continue = false
if deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0 then
if side2 then -- v1 inside, v2 inside
table_insert(output, inputX2)

View File

@ -37,6 +37,7 @@ function SkeletonData.new ()
name,
bones = {},
slots = {},
nameToSlot = {},
skins = {},
defaultSkin = nil,
events = {},
@ -45,8 +46,7 @@ function SkeletonData.new ()
transformConstraints = {},
pathConstraints = {},
x, y, width, height,
version, hash, imagesPath,
slotNameIndices = {}
version, hash, imagesPath
}
setmetatable(self, SkeletonData)
@ -71,15 +71,7 @@ end
function SkeletonData:findSlot (slotName)
if not slotName then error("slotName cannot be nil.", 2) end
for i,slot in ipairs(self.slots) do
if slot.name == slotName then return slot end
end
return nil
end
function SkeletonData:findSlotIndex (slotName)
if not slotName then error("slotName cannot be nil.", 2) end
return self.slotNameIndices[slotName] or -1
return self.nameToSlot[slotName]
end
function SkeletonData:findSkin (skinName)
@ -130,12 +122,4 @@ function SkeletonData:findPathConstraint (constraintName)
return nil
end
function SkeletonData:findPathConstraintIndex (constraintName)
if not constraintName then error("constraintName cannot be nil.", 2) end
for i,constraint in ipairs(self.pathConstraints) do
if constraint.name == constraintName then return i end
end
return -1
end
return SkeletonData

View File

@ -65,6 +65,8 @@ function SkeletonJson.new (attachmentLoader)
local readAttachment
local readAnimation
local readCurve
local readTimeline1
local readTimeline2
local getArray
local getValue = function (map, name, default)
@ -83,9 +85,6 @@ function SkeletonJson.new (attachmentLoader)
if skeletonMap then
skeletonData.hash = skeletonMap["hash"]
skeletonData.version = skeletonMap["spine"]
if ("3.8.75" == skeletonData.version) then
error("Unsupported skeleton data, please export with a newer version of Spine.")
end
skeletonData.x = skeletonMap["x"]
skeletonData.y = skeletonMap["y"]
skeletonData.width = skeletonMap["width"]
@ -105,17 +104,25 @@ function SkeletonJson.new (attachmentLoader)
if not parent then error("Parent bone not found: " .. parentName) end
end
local data = BoneData.new(i, boneName, 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.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 = TransformMode[getValue(boneMap, "transform", "normal")]
data.skinRequired = getValue(boneMap, "skin", false)
local color = boneMap["color"]
if color then
data.color = Color.newWith(tonumber(color:sub(1, 2), 16) / 255,
tonumber(color:sub(3, 4), 16) / 255,
tonumber(color:sub(5, 6), 16) / 255,
tonumber(color:sub(7, 8), 16) / 255)
end
table_insert(skeletonData.bones, data)
end
@ -138,18 +145,17 @@ function SkeletonJson.new (attachmentLoader)
local dark = slotMap["dark"]
if dark then
data.darkColor = Color.newWith(1, 1, 1, 1)
data.darkColor:set(tonumber(dark:sub(1, 2), 16) / 255,
data.darkColor = Color.newWith(
tonumber(dark:sub(1, 2), 16) / 255,
tonumber(dark:sub(3, 4), 16) / 255,
tonumber(dark:sub(5, 6), 16) / 255,
0)
tonumber(dark:sub(5, 6), 16) / 255, 0)
end
data.attachmentName = getValue(slotMap, "attachment", nil)
data.blendMode = BlendMode[getValue(slotMap, "blend", "normal")]
table_insert(skeletonData.slots, data)
skeletonData.slotNameIndices[data.name] = #skeletonData.slots
skeletonData.nameToSlot[data.name] = data
end
end
@ -204,17 +210,19 @@ function SkeletonJson.new (attachmentLoader)
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.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.rotateMix = getValue(constraintMap, "rotateMix", 1);
data.translateMix = getValue(constraintMap, "translateMix", 1);
data.scaleMix = getValue(constraintMap, "scaleMix", 1);
data.shearMix = getValue(constraintMap, "shearMix", 1);
data.mixRotate = getValue(constraintMap, "rotateMix", 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)
table_insert(skeletonData.transformConstraints, data)
end
@ -222,8 +230,8 @@ function SkeletonJson.new (attachmentLoader)
-- Path constraints
if root["path"] then
for _,constraintMap in ipairs(root.path) do
local data = PathConstraintData.new(constraintMap.name);
for _,constraintMap in ipairs(root["path"]) do
local data = PathConstraintData.new(constraintMap.name)
data.order = getValue(constraintMap, "order", 0)
data.skinRequired = getValue(constraintMap, "skin", false)
@ -233,20 +241,21 @@ function SkeletonJson.new (attachmentLoader)
table_insert(data.bones, bone)
end
local targetName = constraintMap.target;
local targetName = constraintMap.target
data.target = skeletonData:findSlot(targetName)
if data.target == nil then error("Path target slot not found: " .. targetName, 2) end
data.positionMode = PathConstraintData.PositionMode[getValue(constraintMap, "positionMode", "percent"):lower()]
data.spacingMode = PathConstraintData.SpacingMode[getValue(constraintMap, "spacingMode", "length"):lower()]
data.rotateMode = PathConstraintData.RotateMode[getValue(constraintMap, "rotateMode", "tangent"):lower()]
data.offsetRotation = getValue(constraintMap, "rotation", 0);
data.position = getValue(constraintMap, "position", 0);
data.offsetRotation = getValue(constraintMap, "rotation", 0)
data.position = getValue(constraintMap, "position", 0)
if data.positionMode == PathConstraintData.PositionMode.fixed then data.position = data.position * scale end
data.spacing = getValue(constraintMap, "spacing", 0);
data.spacing = getValue(constraintMap, "spacing", 0)
if data.spacingMode == PathConstraintData.SpacingMode.length or data.spacingMode == PathConstraintData.SpacingMode.fixed then data.spacing = data.spacing * scale end
data.rotateMix = getValue(constraintMap, "rotateMix", 1);
data.translateMix = getValue(constraintMap, "translateMix", 1);
data.mixRotate = getValue(constraintMap, "mixRotate", 1)
data.mixX = getValue(constraintMap, "mixX", 1)
data.mixY = getValue(constraintMap, "mixY", data.mixX)
table_insert(skeletonData.pathConstraints, data)
end
@ -290,7 +299,7 @@ function SkeletonJson.new (attachmentLoader)
end
for slotName,slotMap in pairs(skinMap.attachments) do
local slotIndex = skeletonData.slotNameIndices[slotName]
local slotIndex = skeletonData:findSlot(slotName).index
for attachmentName,attachmentMap in pairs(slotMap) do
local attachment = readAttachment(attachmentMap, skin, slotIndex, attachmentName, skeletonData)
if attachment then
@ -360,11 +369,11 @@ function SkeletonJson.new (attachmentLoader)
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.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
local color = map["color"]
if color then
@ -453,7 +462,7 @@ function SkeletonJson.new (attachmentLoader)
tonumber(color:sub(5, 6), 16) / 255,
tonumber(color:sub(7, 8), 16) / 255)
end
return path;
return path
elseif type == AttachmentType.point then
local point = self.attachmentLoader:newPointAttachment(skin, name)
@ -536,124 +545,239 @@ function SkeletonJson.new (attachmentLoader)
readAnimation = function (map, name, skeletonData)
local timelines = {}
local duration = 0
local scale = self.scale
-- Slot timelines
-- Slot timelines.
local slotsMap = map["slots"]
if slotsMap then
for slotName,timelineMap in pairs(slotsMap) do
local slotIndex = skeletonData.slotNameIndices[slotName]
for timelineName,values in pairs(timelineMap) do
if timelineName == "color" then
local timeline = Animation.ColorTimeline.new(#values)
timeline.slotIndex = slotIndex
local frameIndex = 0
for _,valueMap in ipairs(values) do
local color = valueMap["color"]
timeline:setFrame(
frameIndex, getValue(valueMap, "time", 0),
tonumber(color:sub(1, 2), 16) / 255,
tonumber(color:sub(3, 4), 16) / 255,
tonumber(color:sub(5, 6), 16) / 255,
tonumber(color:sub(7, 8), 16) / 255
)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.ColorTimeline.ENTRIES])
elseif timelineName == "twoColor" then
local timeline = Animation.TwoColorTimeline.new(#values)
timeline.slotIndex = slotIndex
local frameIndex = 0
for _,valueMap in ipairs(values) do
local light = valueMap["light"]
local dark = valueMap["dark"]
timeline:setFrame(
frameIndex, getValue(valueMap, "time", 0),
tonumber(light:sub(1, 2), 16) / 255,
tonumber(light:sub(3, 4), 16) / 255,
tonumber(light:sub(5, 6), 16) / 255,
tonumber(light:sub(7, 8), 16) / 255,
tonumber(dark:sub(1, 2), 16) / 255,
tonumber(dark:sub(3, 4), 16) / 255,
tonumber(dark:sub(5, 6), 16) / 255
)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.TwoColorTimeline.ENTRIES])
for slotName,slotMap in pairs(slotsMap) do
local slotIndex = skeletonData:findSlot(slotName).index
for timelineName,timelineMap in pairs(slotMap) do
if not timelineMap then
elseif timelineName == "attachment" then
local timeline = Animation.AttachmentTimeline.new(#values)
timeline.slotIndex = slotIndex
local frameIndex = 0
for _,valueMap in ipairs(values) do
local attachmentName = valueMap["name"]
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), attachmentName)
frameIndex = frameIndex + 1
local timeline = Animation.AttachmentTimeline.new(#timelineMap, slotIndex)
for i,keyMap in ipairs(timelineMap) do
timeline:setFrame(i + 1, getValue(keyMap, "time", 0), keyMap["name"])
end
table_insert(timelines, timeline)
elseif timelineName == "rgba" then
local timeline = Animation.RGBATimeline.new(#timelineMap, #timelineMap * 4, slotIndex)
local keyMap = timelineMap[1]
local time = getValue(keyMap, "time", 0)
local color = keyMap["color"]
local r = tonumber(color:sub(1, 2), 16) / 255
local g = tonumber(color:sub(3, 4), 16) / 255
local b = tonumber(color:sub(5, 6), 16) / 255
local a = tonumber(color:sub(7, 8), 16) / 255
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, r, g, b, a)
local nextMap = timelineMap[i + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
color = nextMap["color"]
local nr = tonumber(color:sub(1, 2), 16) / 255
local ng = tonumber(color:sub(3, 4), 16) / 255
local nb = tonumber(color:sub(5, 6), 16) / 255
local na = tonumber(color:sub(7, 8), 16) / 255
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1)
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1)
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na, 1)
end
time = time2
r = nr
g = ng
b = nb
a = na
end
table_insert(timelines, timeline)
elseif timelineName == "rgb" then
local timeline = Animation.RGBTimeline.new(#timelineMap, #timelineMap * 3, slotIndex)
local keyMap = timelineMap[1]
local time = getValue(keyMap, "time", 0)
local color = keyMap["color"]
local r = tonumber(color:sub(1, 2), 16) / 255
local g = tonumber(color:sub(3, 4), 16) / 255
local b = tonumber(color:sub(5, 6), 16) / 255
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, r, g, b)
local nextMap = timelineMap[i + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
color = nextMap["color"]
local nr = tonumber(color:sub(1, 2), 16) / 255
local ng = tonumber(color:sub(3, 4), 16) / 255
local nb = tonumber(color:sub(5, 6), 16) / 255
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1)
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1)
end
time = time2
r = nr
g = ng
b = nb
end
table_insert(timelines, timeline)
elseif timelineName == "alpha" then
table_insert(timelines, readTimeline1(timelineMap, Animation.AlphaTimeline.new(#timelineMap, #timelineMap, slotIndex), 0, 1))
elseif timelineName == "rgba2" then
local timeline = Animation.RGBA2Timeline.new(#timelineMap, #timelineMap * 7, slotIndex)
local keyMap = timelineMap[1]
local time = getValue(keyMap, "time", 0)
local color = keyMap["light"]
local r = tonumber(color:sub(1, 2), 16) / 255
local g = tonumber(color:sub(3, 4), 16) / 255
local b = tonumber(color:sub(5, 6), 16) / 255
local a = tonumber(color:sub(7, 8), 16) / 255
color = keyMap["dark"]
local r2 = tonumber(color:sub(1, 2), 16) / 255
local g2 = tonumber(color:sub(3, 4), 16) / 255
local b2 = tonumber(color:sub(5, 6), 16) / 255
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, r, g, b, a, r2, g2, b2)
local nextMap = timelineMap[i + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
color = nextMap["light"]
local nr = tonumber(color:sub(1, 2), 16) / 255
local ng = tonumber(color:sub(3, 4), 16) / 255
local nb = tonumber(color:sub(5, 6), 16) / 255
local na = tonumber(color:sub(7, 8), 16) / 255
color = nextMap["dark"]
local nr2 = tonumber(color:sub(1, 2), 16) / 255
local ng2 = tonumber(color:sub(3, 4), 16) / 255
local nb2 = tonumber(color:sub(5, 6), 16) / 255
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1)
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1)
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na, 1)
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, r2, nr2, 1)
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, g2, ng2, 1)
bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, b2, nb2, 1)
end
time = time2
r = nr
g = ng
b = nb
a = na
r2 = nr2
g2 = ng2
b2 = nb2
end
table_insert(timelines, timeline)
elseif timelineName == "rgb2" then
local timeline = Animation.RGB2Timeline.new(#timelineMap, #timelineMap * 6, slotIndex)
local keyMap = timelineMap[1]
local time = getValue(keyMap, "time", 0)
local color = keyMap["light"]
local r = tonumber(color:sub(1, 2), 16) / 255
local g = tonumber(color:sub(3, 4), 16) / 255
local b = tonumber(color:sub(5, 6), 16) / 255
color = keyMap["dark"]
local r2 = tonumber(color:sub(1, 2), 16) / 255
local g2 = tonumber(color:sub(3, 4), 16) / 255
local b2 = tonumber(color:sub(5, 6), 16) / 255
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, r, g, b, r2, g2, b2)
local nextMap = timelineMap[i + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
color = nextMap["light"]
local nr = tonumber(color:sub(1, 2), 16) / 255
local ng = tonumber(color:sub(3, 4), 16) / 255
local nb = tonumber(color:sub(5, 6), 16) / 255
color = nextMap["dark"]
local nr2 = tonumber(color:sub(1, 2), 16) / 255
local ng2 = tonumber(color:sub(3, 4), 16) / 255
local nb2 = tonumber(color:sub(5, 6), 16) / 255
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1)
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1)
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, r2, nr2, 1)
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, g2, ng2, 1)
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, b2, nb2, 1)
end
time = time2
r = nr
g = ng
b = nb
r2 = nr2
g2 = ng2
b2 = nb2
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
else
error("Invalid frame type for a slot: " .. timelineName .. " (" .. slotName .. ")")
error("Invalid timeline type for a slot: " .. timelineName .. " (" .. slotName .. ")")
end
end
end
end
-- Bone timelines
-- Bone timelines.
local bonesMap = map["bones"]
if bonesMap then
for boneName,timelineMap in pairs(bonesMap) do
for boneName,boneMap in pairs(bonesMap) do
local boneIndex = skeletonData:findBoneIndex(boneName)
if boneIndex == -1 then error("Bone not found: " .. boneName) end
for timelineName,values in pairs(timelineMap) do
if timelineName == "rotate" then
local timeline = Animation.RotateTimeline.new(#values)
timeline.boneIndex = boneIndex
local frameIndex = 0
for _,valueMap in ipairs(values) do
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "angle", 0))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.RotateTimeline.ENTRIES])
elseif timelineName == "translate" or timelineName == "scale" or timelineName == "shear" then
local timeline
local timelineScale = 1
local defaultValue = 0
if timelineName == "scale" then
timeline = Animation.ScaleTimeline.new(#values)
defaultValue = 1
elseif timelineName == "shear" then
timeline = Animation.ShearTimeline.new(#values)
else
timeline = Animation.TranslateTimeline.new(#values)
timelineScale = self.scale
end
timeline.boneIndex = boneIndex
local frameIndex = 0
for _,valueMap in ipairs(values) do
local x = getValue(valueMap, "x", defaultValue) * timelineScale
local y = getValue(valueMap, "y", defaultValue) * timelineScale
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), x, y)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.TranslateTimeline.ENTRIES])
for timelineName,timelineMap in pairs(boneMap) do
if not timelineMap then
elseif timelineName == "rotate" then
table_insert(timelines, readTimeline1(timelineMap, Animation.RotateTimeline.new(#timelineMap, #timelineMap, boneIndex), 0, 1))
elseif timelineName == "translate" then
local timeline = Animation.TranslateTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
table_insert(timelines, readTimeline2(timelineMap, timeline, "x", "y", 0, scale))
elseif timelineName == "translatex" then
local timeline = Animation.TranslateXTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, scale))
elseif timelineName == "translatey" then
local timeline = Animation.TranslateYTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, scale))
elseif timelineName == "scale" then
local timeline = Animation.ScaleTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 1, 1))
elseif timelineName == "scalex" then
local timeline = Animation.ScaleXTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
elseif timelineName == "scaley" then
local timeline = Animation.ScaleYTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
elseif timelineName == "shear" then
local timeline = Animation.ShearTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 0, 1))
elseif timelineName == "shearx" then
local timeline = Animation.ShearXTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, 1))
elseif timelineName == "sheary" then
local timeline = Animation.ShearYTimeline.new(#timelineMap, #timelineMap, boneIndex)
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, 1))
else
error("Invalid timeline type for a bone: " .. timelineName .. " (" .. boneName .. ")")
end
@ -664,96 +788,169 @@ function SkeletonJson.new (attachmentLoader)
-- IK timelines.
local ik = map["ik"]
if ik then
for ikConstraintName,values in pairs(ik) do
local ikConstraint = skeletonData:findIkConstraint(ikConstraintName)
local timeline = Animation.IkConstraintTimeline.new(#values)
for i,other in pairs(skeletonData.ikConstraints) do
if other == ikConstraint then
timeline.ikConstraintIndex = i
break
for constraintName,timelineMap in pairs(ik) do
local keyMap = timelineMap[1]
if keyMap then
local constraintIndex = -1
for i,other in pairs(skeletonData.ikConstraints) do
if other.name == constraintName then
constraintIndex = i
break
end
end
local timeline = Animation.IkConstraintTimeline.new(#timelineMap, #timelineMap * 2, constraintIndex)
local time = getValue(keyMap, "time", 0)
local mix = getValue(keyMap, "mix", 1)
local softness = getValue(keyMap, "softness", 0) * scale
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
local bendPositive = 1
local compress = false
local stretch = false
if keyMap["bendPositive"] == false then bendPositive = -1 end
if keyMap["compress"] ~= nil then compress = keyMap["compress"] end
if keyMap["stretch"] ~= nil then stretch = keyMap["stretch"] end
timeline:setFrame(frame, time, mix, softness, bendPositive, compress, stretch)
local nextMap = timelineMap[i + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
color = nextMap["color"]
local mix2 = getValue(nextMap, "mix", 1)
local softness2 = getValue(nextMap, "softness", 0) * scale
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale)
end
time = time2
mix = mix2
softness = softness2
end
end
local frameIndex = 0
for _,valueMap in ipairs(values) do
local mix = 1
local softness = 0
if valueMap["mix"] ~= nil then mix = valueMap["mix"] end
if valueMap["softness"] ~= nil then softness = valueMap["softness"] * scale end
local bendPositive = 1
if valueMap["bendPositive"] == false then bendPositive = -1 end
local stretch = false
if valueMap["stretch"] ~= nil then stretch = valueMap["stretch"] end
local compress = false
if valueMap["compress"] ~= nil then compress = valueMap["compress"] end
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), mix, softness, bendPositive, compress, stretch)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.IkConstraintTimeline.ENTRIES])
end
end
-- Transform constraint timelines.
local transform = map["transform"]
if transform then
for constraintName, values in pairs(transform) do
local constraint = skeletonData:findTransformConstraint(constraintName)
local timeline = Animation.TransformConstraintTimeline.new(#values)
for i,other in pairs(skeletonData.transformConstraints) do
if other == constraint then
timeline.transformConstraintIndex = i
break
for constraintName, timelineMap in pairs(transform) do
local keyMap = timelineMap[1]
if keyMap then
local constraintIndex = -1
for i,other in pairs(skeletonData.transformConstraints) do
if other.name == constraintName then
constraintIndex = i
break
end
end
local timeline = Animation.TransformConstraintTimeline.new(#timelineMap, #timelineMap * 4, constraintIndex)
local time = getValue(keyMap, "time", 0)
local mixRotate = getValue(keyMap, "mixRotate", 0)
local mixX = getValue(keyMap, "mixX", 1)
local mixY = getValue(keyMap, "mixY", mixX)
local mixScaleX = getValue(keyMap, "mixScaleX", 1)
local mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX)
local mixShearY = getValue(keyMap, "mixShearY", 1)
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY)
local nextMap = timelineMap[frame + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
local mixRotate2 = getValue(nextMap, "mixRotate", 1)
local mixX2 = getValue(nextMap, "mixX", 1)
local mixY2 = getValue(nextMap, "mixY", mixX2)
local mixScaleX2 = getValue(nextMap, "mixScaleX", 1)
local mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2)
local mixShearY2 = getValue(nextMap, "mixShearY", 1)
local curve = keyMap.curve
if curve then
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)
end
time = time2
mixRotate = mixRotate2
mixX = mixX2
mixY = mixY2
mixScaleX = mixScaleX2
mixScaleY = mixScaleY2
mixScaleX = mixScaleX2
end
table_insert(timelines, timeline)
end
local frameIndex = 0
for _,valueMap in ipairs(values) do
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1), getValue(valueMap, "scaleMix", 1), getValue(valueMap, "shearMix", 1))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.TransformConstraintTimeline.ENTRIES])
end
end
-- Path constraint timelines.
if map.path then
for constraintName,constraintMap in pairs(map.path) do
local index = skeletonData:findPathConstraintIndex(constraintName)
if index == -1 then error("Path constraint not found: " .. constraintName, 2) end
local data = skeletonData.pathConstraints[index]
local constraint, constraintIndex = -1
for i,other in pairs(skeletonData.transformConstraints) do
if other.name == constraintName then
constraintIndex = i
constraint = other
break
end
end
for timelineName, timelineMap in pairs(constraintMap) do
if timelineName == "position" or timelineName == "spacing" then
local timeline = nil
local timelineScale = 1
if timelineName == "spacing" then
timeline = Animation.PathConstraintSpacingTimeline.new(#timelineMap)
if data.spacingMode == PathConstraintData.SpacingMode.length or data.spacingMode == PathConstraintData.SpacingMode.fixed then timelineScale = scale end
else
timeline = Animation.PathConstraintPositionTimeline.new(#timelineMap)
if data.positionMode == PathConstraintData.PositionMode.fixed then timelineScale = scale end
local keyMap = timelineMap[1]
if keyMap then
if timelineName == "position" then
local timeline = Animation.PathConstraintPositionTimeline.new(#timelineMap, #timelineMap, constraintIndex)
local timelineScale = 1
if constraint.positionMode == PositionMode.fixed then timelineScale = scale end
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, timelineScale))
elseif timelineName == "spacing" then
local timeline = Animation.PathConstraintSpacingTimeline.new(#timelineMap, #timelineMap, constraintIndex)
local timelineScale = 1;
if data.spacingMode == SpacingMode.Length or data.spacingMode == SpacingMode.Fixed then timelineScale = scale end
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, timelineScale))
elseif timelineName == "mix" then
local timeline = Animation.PathConstraintMixTimeline.new(#timelineMap, #timelineMap * 3, constraintIndex)
local time = getValue(keyMap, "time", 0)
local mixRotate = getValue(keyMap, "mixRotate", 1)
local mixX = getValue(keyMap, "mixX", 1)
local mixY = getValue(keyMap, "mixY", mixX)
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local frame = i - 1
timeline:setFrame(frame, time, mixRotate, mixX, mixY)
local nextMap = timelineMap[frame + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
local mixRotate2 = getValue(nextMap, "mixRotate", 1)
local mixX2 = getValue(nextMap, "mixX", 1)
local mixY2 = getValue(nextMap, "mixY", mixX2)
local curve = keyMap.curve
if curve then
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)
end
time = time2
mixRotate = mixRotate2
mixX = mixX2
mixY = mixY2
keyMap = nextMap
end
table_insert(timelines, timeline)
end
timeline.pathConstraintIndex = index
local frameIndex = 0
for _,valueMap in ipairs(timelineMap) do
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, timelineName, 0) * timelineScale)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.PathConstraintPositionTimeline.ENTRIES])
elseif timelineName == "mix" then
local timeline = Animation.PathConstraintMixTimeline.new(#timelineMap)
timeline.pathConstraintIndex = index
local frameIndex = 0
for _,valueMap in ipairs(timelineMap) do
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.PathConstraintMixTimeline.ENTRIES])
end
end
end
@ -765,68 +962,72 @@ function SkeletonJson.new (attachmentLoader)
local skin = skeletonData:findSkin(deformName)
if not skin then error("Skin not found: " .. deformName, 2) end
for slotName,slotMap in pairs(deformMap) do
local slotIndex = skeletonData:findSlotIndex(slotName)
local slotIndex = skeletonData:findSlot(slotName).index
if slotIndex == -1 then error("Slot not found: " .. slotMap.name, 2) end
for timelineName,timelineMap in pairs(slotMap) do
local attachment = skin:getAttachment(slotIndex, timelineName)
if not attachment then error("Deform attachment not found: " .. timelineMap.name, 2) end
local weighted = attachment.bones ~= nil
local vertices = attachment.vertices;
local deformLength = #vertices
if weighted then deformLength = math.floor(#vertices / 3) * 2 end
local keyMap = timelineMap[1]
if keyMap then
local attachment = skin:getAttachment(slotIndex, timelineName)
if not attachment then error("Deform attachment not found: " .. timelineMap.name, 2) end
local weighted = attachment.bones ~= nil
local vertices = attachment.vertices
local deformLength = #vertices
if weighted then deformLength = math.floor(deformLength / 3) * 2 end
local timeline = Animation.DeformTimeline.new(#timelineMap)
timeline.slotIndex = slotIndex
timeline.attachment = attachment
local frameIndex = 0
for _,valueMap in ipairs(timelineMap) do
local deform = nil
local verticesValue = getValue(valueMap, "vertices", nil)
if verticesValue == nil then
deform = vertices
if weighted then deform = utils.newNumberArray(deformLength) end
else
deform = utils.newNumberArray(deformLength)
local start = getValue(valueMap, "offset", 0) + 1
utils.arrayCopy(verticesValue, 1, deform, start, #verticesValue)
if scale ~= 1 then
local i = start
local n = i + #verticesValue
while i < n do
deform[i] = deform[i] * scale
i = i + 1
local timeline = Animation.DeformTimeline.new(#timelineMap, #timelineMap, slotIndex, attachment)
local bezier = 0
for i,keyMap in ipairs(timelineMap) do
local deform = nil
local verticesValue = getValue(keyMap, "vertices", nil)
if verticesValue == nil then
deform = vertices
if weighted then deform = utils.newNumberArray(deformLength) end
else
deform = utils.newNumberArray(deformLength)
local start = getValue(keyMap, "offset", 0) + 1
utils.arrayCopy(verticesValue, 1, deform, start, #verticesValue)
if scale ~= 1 then
local i = start
local n = i + #verticesValue
while i < n do
deform[i] = deform[i] * scale
i = i + 1
end
end
if not weighted then
local i = 1
local n = i + deformLength
while i < n do
deform[i] = deform[i] + vertices[i]
i = i + 1
end
end
end
if not weighted then
local i = 1
local n = i + deformLength
while i < n do
deform[i] = deform[i] + vertices[i]
i = i + 1
end
local frame = i - 1
timeline:setFrame(frame, time, mixRotate, mixX, mixY)
local nextMap = timelineMap[frame + 1]
if not nextMap then
timeline:shrink(bezier)
break
end
local time2 = getValue(nextMap, "time", 0)
local curve = keyMap.curve
if curve then bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1) end
time = time2
end
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), deform)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
table_insert(timelines, timeline)
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
end
end
end
end
-- Draworder timeline.
local drawOrderValues = map["drawOrder"]
if not drawOrderValues then drawOrderValues = map["draworder"] end
if drawOrderValues then
local timeline = Animation.DrawOrderTimeline.new(#drawOrderValues)
-- Draw order timelines.
if map["drawOrder"] then
local timeline = Animation.DrawOrderTimeline.new(#map["drawOrder"])
local slotCount = #skeletonData.slots
local frameIndex = 0
for _,drawOrderMap in ipairs(drawOrderValues) do
local frame = 0
for _,drawOrderMap in ipairs(map["drawOrder"]) do
local drawOrder = nil
local offsets = drawOrderMap["offsets"]
if offsets then
@ -835,7 +1036,7 @@ function SkeletonJson.new (attachmentLoader)
local originalIndex = 1
local unchangedIndex = 1
for _,offsetMap in ipairs(offsets) do
local slotIndex = skeletonData:findSlotIndex(offsetMap["slot"])
local slotIndex = skeletonData:findSlot(offsetMap["slot"]).index
if slotIndex == -1 then error("Slot not found: " .. offsetMap["slot"]) end
-- Collect unchanged items.
while originalIndex ~= slotIndex do
@ -861,18 +1062,17 @@ function SkeletonJson.new (attachmentLoader)
end
end
end
timeline:setFrame(frameIndex, getValue(drawOrderMap, "time", 0), drawOrder)
frameIndex = frameIndex + 1
timeline:setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder)
frame = frame + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
end
-- Event timeline.
-- Event timelines.
local events = map["events"]
if events then
local timeline = Animation.EventTimeline.new(#events)
local frameIndex = 0
local frame = 0
for _,eventMap in ipairs(events) do
local eventData = skeletonData:findEvent(eventMap["name"])
if not eventData then error("Event not found: " .. eventMap["name"]) end
@ -896,26 +1096,91 @@ function SkeletonJson.new (attachmentLoader)
event.volume = getValue(eventMap, "volume", 1)
event.balance = getValue(eventMap, "balance", 0)
end
timeline:setFrame(frameIndex, event)
frameIndex = frameIndex + 1
timeline:setFrame(frame, event)
frame = frame + 1
end
table_insert(timelines, timeline)
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
end
local duration = 0
for _,timeline in ipairs(timelines) do
duration = math.max(duration, timeline:getDuration())
end
table_insert(skeletonData.animations, Animation.new(name, timelines, duration))
end
readCurve = function (map, timeline, frameIndex)
readCurve = function (map, timeline, frame)
local curve = map["curve"]
if not curve then return end
if curve == "stepped" then
timeline:setStepped(frameIndex)
timeline:setStepped(frame)
else
timeline:setCurve(frameIndex, getValue(map, "curve", 0), getValue(map, "c2", 0), getValue(map, "c3", 1), getValue(map, "c4", 1))
timeline:setCurve(frame, getValue(map, "curve", 0), getValue(map, "c2", 0), getValue(map, "c3", 1), getValue(map, "c4", 1))
end
end
readTimeline1 = function (keys, timeline, defaultValue, scale)
local keyMap = keys[1]
local time = getValue(keyMap, "time", 0)
local value = getValue(keyMap, "value", defaultValue) * scale
local bezier = 0
for i,keyMap in ipairs(keys) do
local frame = i - 1
timeline:setFrame(frame, time, value)
local nextMap = keys[frame + 1]
if not nextMap then break end
local time2 = getValue(nextMap, "time", 0)
local value2 = getValue(nextMap, "value", defaultValue) * scale
local curve = keyMap.curve
if curve then bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale) end
time = time2
value = value2
end
timeline:shrink(bezier)
return timeline
end
readTimeline2 = function (keys, timeline, name1, name2, defaultValue, scale)
local keyMap = keys[1]
local time = getValue(keyMap, "time", 0)
local value1 = getValue(keyMap, name1, defaultValue) * scale
local value2 = getValue(keyMap, name2, defaultValue) * scale
local bezier = 0
for i,keyMap in ipairs(keys) do
local frame = i - 1
timeline:setFrame(frame, time, value1, value2)
local nextMap = keys[frame + 1]
if not nextMap then break end
local time2 = getValue(nextMap, "time", 0)
local nvalue1 = getValue(nextMap, name1, defaultValue) * scale
local nvalue2 = getValue(nextMap, name2, defaultValue) * scale
local curve = keyMap.curve
if curve then
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale)
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale)
end
time = time2
value1 = nvalue1
value2 = nvalue2
end
timeline:shrink(bezier)
return timeline
end
readCurve = function (curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale)
if curve == "stepped" then
if value ~= 0 then timeline.setStepped(frame) end
return bezier
end
local i = value * 4
local cx1 = curve[i]
local cy1 = curve[i + 1] * scale
local cx2 = curve[i + 2]
local cy2 = curve[i + 3] * scale
timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2)
return bezier + 1
end
getArray = function (map, name, scale)
local list = map[name]
local values = {}

View File

@ -97,7 +97,7 @@ function TransformConstraint:applyAbsoluteWorld ()
local tb = target.b
local tc = target.c
local td = target.d
local degRadReflect = 0;
local degRadReflect = 0
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
local offsetRotation = self.data.offsetRotation * degRadReflect
local offsetShearY = self.data.offsetShearY * degRadReflect
@ -184,7 +184,7 @@ function TransformConstraint:applyRelativeWorld ()
local tb = target.b
local tc = target.c
local td = target.d
local degRadReflect = 0;
local degRadReflect = 0
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
local offsetRotation = self.data.offsetRotation * degRadReflect
local offsetShearY = self.data.offsetShearY * degRadReflect
@ -242,7 +242,7 @@ function TransformConstraint:applyRelativeWorld ()
end
local b = bone.b
local d = bone.d
r = math_atan2(d, b) + (r - math_pi / 2 + offsetShearY) * shearMix;
r = math_atan2(d, b) + (r - math_pi / 2 + offsetShearY) * shearMix
local s = math_sqrt(b * b + d * d)
bone.b = math_cos(r) * s
bone.d = math_sin(r) * s
@ -297,7 +297,7 @@ function TransformConstraint:applyAbsoluteLocal ()
bone.shearY = bone.shearY + r * shearMix
end
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY)
end
end

View File

@ -74,7 +74,7 @@ function Triangulator:triangulate (verticesArray)
end
self.triangles = {}
local triangles = self.triangles;
local triangles = self.triangles
while vertexCount > 3 do
-- Find ear tip.
@ -122,7 +122,7 @@ function Triangulator:triangulate (verticesArray)
if _next == 0 then
repeat
if not isConcave[i] then
break;
break
end
i = i - 1
until i == 0
@ -171,10 +171,10 @@ function Triangulator:decompose(verticesArray, triangles)
local vertices = verticesArray
self.convexPolygons = {}
local convexPolygons = self.convexPolygons;
local convexPolygons = self.convexPolygons
self.convexPolygonsIndices = {}
local convexPolygonsIndices = self.convexPolygonsIndices;
local convexPolygonsIndices = self.convexPolygonsIndices
local polygonIndices = {}
local polygon = {}
@ -197,12 +197,12 @@ function Triangulator:decompose(verticesArray, triangles)
local y3 = vertices[t3 + 1]
-- If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).
local merged = false;
local merged = false
if fanBaseIndex == t1 then
local o = #polygon - 4 + 1;
local p = polygon;
local winding1 = self:winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
local winding2 = self:winding(x3, y3, p[1], p[2], p[3], p[4]);
local o = #polygon - 4 + 1
local p = polygon
local winding1 = self:winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3)
local winding2 = self:winding(x3, y3, p[1], p[2], p[3], p[4])
if winding1 == lastWinding and winding2 == lastWinding then
table_insert(polygon, x3)
table_insert(polygon, y3)
@ -226,8 +226,8 @@ function Triangulator:decompose(verticesArray, triangles)
table_insert(polygon, y3)
polygonIndices = {}
table_insert(polygonIndices, t1)
table_insert(polygonIndices, t2);
table_insert(polygonIndices, t3);
table_insert(polygonIndices, t2)
table_insert(polygonIndices, t3)
lastWinding = self:winding(x1, y1, x2, y2, x3, y3)
fanBaseIndex = t1
end
@ -266,11 +266,11 @@ function Triangulator:decompose(verticesArray, triangles)
if ii ~= i then
local otherIndices = convexPolygonsIndices[ii]
if (#otherIndices == 3) then
local otherFirstIndex = otherIndices[1];
local otherSecondIndex = otherIndices[2];
local otherLastIndex = otherIndices[3];
local otherFirstIndex = otherIndices[1]
local otherSecondIndex = otherIndices[2]
local otherLastIndex = otherIndices[3]
local otherPoly = convexPolygons[ii];
local otherPoly = convexPolygons[ii]
local x3 = otherPoly[#otherPoly - 2 + 1]
local y3 = otherPoly[#otherPoly - 1 + 1]
@ -308,14 +308,14 @@ function Triangulator:decompose(verticesArray, triangles)
i = i - 1
end
return convexPolygons;
return convexPolygons
end
function Triangulator:isConcave(index, vertexCount, vertices, indices)
local previous = indices[(vertexCount + index - 1) % vertexCount] * 2 + 1;
local current = indices[index] * 2 + 1;
local _next = indices[(index + 1) % vertexCount] * 2 + 1;
return not self:positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[_next],vertices[_next + 1]);
local previous = indices[(vertexCount + index - 1) % vertexCount] * 2 + 1
local current = indices[index] * 2 + 1
local _next = indices[(index + 1) % vertexCount] * 2 + 1
return not self:positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[_next],vertices[_next + 1])
end
function Triangulator:positiveArea(p1x, p1y, p2x, p2y, p3x, p3y)
@ -328,7 +328,7 @@ function Triangulator:winding(p1x, p1y, p2x, p2y, p3x, p3y)
if p3x * py - p3y * px + px * p1y - p1x * py >= 0 then
return 1
else
return -1;
return -1
end
end

View File

@ -84,8 +84,8 @@ function MeshAttachment:updateUVs ()
local i = 0
local n = #uvs
while i < n do
uvs[i + 1] = u + regionUVs[i + 2] * width;
uvs[i + 2] = v + (1 - regionUVs[i + 1]) * height;
uvs[i + 1] = u + regionUVs[i + 2] * width
uvs[i + 2] = v + (1 - regionUVs[i + 1]) * height
i = i + 2
end
elseif region.degrees == 180 then
@ -96,8 +96,8 @@ function MeshAttachment:updateUVs ()
local i = 0
local n = #uvs
while i < n do
uvs[i + 1] = u + (1 - regionUVs[i + 1]) * width;
uvs[i + 2] = v + (1 - regionUVs[i + 2]) * height;
uvs[i + 1] = u + (1 - regionUVs[i + 1]) * width
uvs[i + 2] = v + (1 - regionUVs[i + 2]) * height
i = i + 2
end
elseif region.degrees == 270 then
@ -108,20 +108,20 @@ function MeshAttachment:updateUVs ()
local i = 0
local n = #uvs
while i < n do
uvs[i + 1] = u + (1 - regionUVs[i + 2]) * width;
uvs[i + 2] = v + regionUVs[i + 1] * height;
uvs[i + 1] = u + (1 - regionUVs[i + 2]) * width
uvs[i + 2] = v + regionUVs[i + 1] * height
i = i + 2
end
else
u = region.u - region.offsetX / textureWidth;
v = region.v - (region.originalHeight - region.offsetY - region.height) / textureHeight;
width = region.originalWidth / textureWidth;
height = region.originalHeight / textureHeight;
u = region.u - region.offsetX / textureWidth
v = region.v - (region.originalHeight - region.offsetY - region.height) / textureHeight
width = region.originalWidth / textureWidth
height = region.originalHeight / textureHeight
local i = 0
local n = #uvs
while i < n do
uvs[i + 1] = u + regionUVs[i + 1] * width;
uvs[i + 2] = v + regionUVs[i + 2] * height;
uvs[i + 1] = u + regionUVs[i + 1] * width
uvs[i + 2] = v + regionUVs[i + 2] * height
i = i + 2
end
end

View File

@ -155,6 +155,7 @@ function RegionAttachment.new (name)
end
function RegionAttachment:updateOffset ()
if not self.region then return end
local regionScaleX = self.width / self.region.originalWidth * self.scaleX
local regionScaleY = self.height / self.region.originalHeight * self.scaleY
local localX = -self.width / 2 * self.scaleX + self.region.offsetX * regionScaleX

View File

@ -36,8 +36,8 @@ local utils = require "spine-lua.utils"
local AttachmentType = require "spine-lua.attachments.AttachmentType"
local Attachment = require "spine-lua.attachments.Attachment"
local nextID = 0;
local SHL_11 = 2048;
local nextID = 0
local SHL_11 = 2048
local VertexAttachment = {}
VertexAttachment.__index = VertexAttachment