mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
[lua] SkeletonJson 4.0 port, clean up.
This commit is contained in:
parent
7df74c2fa4
commit
3c0a43687b
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = {}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user