mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +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
|
end
|
||||||
self:clear()
|
self:clear()
|
||||||
|
|
||||||
self.drainDisabled = false;
|
self.drainDisabled = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function EventQueue:clear ()
|
function EventQueue:clear ()
|
||||||
@ -326,7 +326,7 @@ function AnimationState:updateMixingFrom (to, delta)
|
|||||||
|
|
||||||
from.trackTime = from.trackTime + delta * from.timeScale
|
from.trackTime = from.trackTime + delta * from.timeScale
|
||||||
to.mixTime = to.mixTime + delta
|
to.mixTime = to.mixTime + delta
|
||||||
return false;
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function AnimationState:apply (skeleton)
|
function AnimationState:apply (skeleton)
|
||||||
@ -388,7 +388,7 @@ function AnimationState:apply (skeleton)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:queueEvents(current, animationTime)
|
self:queueEvents(current, animationTime)
|
||||||
self.events = {};
|
self.events = {}
|
||||||
current.nextAnimationLast = animationTime
|
current.nextAnimationLast = animationTime
|
||||||
current.nextTrackLast = current.trackTime
|
current.nextTrackLast = current.trackTime
|
||||||
end
|
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
|
-- 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).
|
-- the time is before the first key).
|
||||||
local setupState = self.unkeyedState + SETUP
|
local setupState = self.unkeyedState + SETUP
|
||||||
local slots = skeleton.slots;
|
local slots = skeleton.slots
|
||||||
for _, slot in ipairs(slots) do
|
for _, slot in ipairs(slots) do
|
||||||
if slot.attachmentState == setupState then
|
if slot.attachmentState == setupState then
|
||||||
local attachmentName = slot.data.attachmentName
|
local attachmentName = slot.data.attachmentName
|
||||||
@ -411,7 +411,7 @@ function AnimationState:apply (skeleton)
|
|||||||
end
|
end
|
||||||
end
|
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()
|
queue:drain()
|
||||||
@ -453,11 +453,11 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
|||||||
local firstFrame = #from.timelinesRotation == 0
|
local firstFrame = #from.timelinesRotation == 0
|
||||||
local timelinesRotation = from.timelinesRotation
|
local timelinesRotation = from.timelinesRotation
|
||||||
|
|
||||||
from.totalAlpha = 0;
|
from.totalAlpha = 0
|
||||||
|
|
||||||
for i,timeline in ipairs(timelines) do
|
for i,timeline in ipairs(timelines) do
|
||||||
local skipSubsequent = false;
|
local skipSubsequent = false
|
||||||
local direction = MixDirection.out;
|
local direction = MixDirection.out
|
||||||
local timelineBlend = MixBlend.setup
|
local timelineBlend = MixBlend.setup
|
||||||
local alpha = 0
|
local alpha = 0
|
||||||
if timelineMode[i] == SUBSEQUENT then
|
if timelineMode[i] == SUBSEQUENT then
|
||||||
@ -498,7 +498,7 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
|||||||
if (to.mixDuration > 0) then
|
if (to.mixDuration > 0) then
|
||||||
self:queueEvents(from, animationTime)
|
self:queueEvents(from, animationTime)
|
||||||
end
|
end
|
||||||
self.events = {};
|
self.events = {}
|
||||||
from.nextAnimationLast = animationTime
|
from.nextAnimationLast = animationTime
|
||||||
from.nextTrackLast = from.trackTime
|
from.nextTrackLast = from.trackTime
|
||||||
|
|
||||||
@ -506,20 +506,20 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function AnimationState:applyAttachmentTimeline(timeline, skeleton, time, blend, attachments)
|
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
|
if slot.bone.active == false then return end
|
||||||
|
|
||||||
local frames = timeline.frames
|
local frames = timeline.frames
|
||||||
if time < frames[0] then -- Time is before first frame.
|
if time < frames[0] then -- Time is before first frame.
|
||||||
if blend == MixBlend.setup or blend == MixBlend.first then
|
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
|
end
|
||||||
else
|
else
|
||||||
local frameIndex = 0
|
local frameIndex = 0
|
||||||
if (time >= frames[zlen(frames) - 1]) then -- Time is after last frame.
|
if (time >= frames[zlen(frames) - 1]) then -- Time is after last frame.
|
||||||
frameIndex = zlen(frames) - 1;
|
frameIndex = zlen(frames) - 1
|
||||||
else
|
else
|
||||||
frameIndex = Animation.binarySearch(frames, time, 1) - 1;
|
frameIndex = Animation.binarySearch(frames, time, 1) - 1
|
||||||
end
|
end
|
||||||
self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
|
self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
|
||||||
end
|
end
|
||||||
@ -665,7 +665,7 @@ function AnimationState:clearTracks ()
|
|||||||
local queue = self.queue
|
local queue = self.queue
|
||||||
local tracks = self.tracks
|
local tracks = self.tracks
|
||||||
local oldDrainDisabled = queue.drainDisabled
|
local oldDrainDisabled = queue.drainDisabled
|
||||||
queue.drainDisabled = true;
|
queue.drainDisabled = true
|
||||||
local numTracks = getNumTracks(tracks)
|
local numTracks = getNumTracks(tracks)
|
||||||
local i = 0
|
local i = 0
|
||||||
while i <= numTracks do
|
while i <= numTracks do
|
||||||
@ -673,7 +673,7 @@ function AnimationState:clearTracks ()
|
|||||||
end
|
end
|
||||||
tracks = {}
|
tracks = {}
|
||||||
queue.drainDisabled = oldDrainDisabled
|
queue.drainDisabled = oldDrainDisabled
|
||||||
queue:drain();
|
queue:drain()
|
||||||
end
|
end
|
||||||
|
|
||||||
function AnimationState:clearTrack (trackIndex)
|
function AnimationState:clearTrack (trackIndex)
|
||||||
@ -686,7 +686,7 @@ function AnimationState:clearTrack (trackIndex)
|
|||||||
|
|
||||||
self:disposeNext(current)
|
self:disposeNext(current)
|
||||||
|
|
||||||
local entry = current;
|
local entry = current
|
||||||
while (true) do
|
while (true) do
|
||||||
local from = entry.mixingFrom
|
local from = entry.mixingFrom
|
||||||
if from == nil then break end
|
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)
|
current.interruptAlpha = current.interruptAlpha * math_min(1, from.mixTime / from.mixDuration)
|
||||||
end
|
end
|
||||||
|
|
||||||
from.timelinesRotation = {};
|
from.timelinesRotation = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
queue:start(current)
|
queue:start(current)
|
||||||
@ -731,7 +731,7 @@ end
|
|||||||
|
|
||||||
function AnimationState:setAnimation (trackIndex, animation, loop)
|
function AnimationState:setAnimation (trackIndex, animation, loop)
|
||||||
if not animation then error("animation cannot be null.") end
|
if not animation then error("animation cannot be null.") end
|
||||||
local interrupt = true;
|
local interrupt = true
|
||||||
local current = self:expandToIndex(trackIndex)
|
local current = self:expandToIndex(trackIndex)
|
||||||
local queue = self.queue
|
local queue = self.queue
|
||||||
local tracks = self.tracks
|
local tracks = self.tracks
|
||||||
@ -743,7 +743,7 @@ function AnimationState:setAnimation (trackIndex, animation, loop)
|
|||||||
queue:_end(current)
|
queue:_end(current)
|
||||||
self:disposeNext(current)
|
self:disposeNext(current)
|
||||||
current = current.mixingFrom
|
current = current.mixingFrom
|
||||||
interrupt = false;
|
interrupt = false
|
||||||
else
|
else
|
||||||
self:disposeNext(current)
|
self:disposeNext(current)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -40,13 +40,12 @@ local math_pi = math.pi
|
|||||||
local TransformMode = require "spine-lua.TransformMode"
|
local TransformMode = require "spine-lua.TransformMode"
|
||||||
|
|
||||||
function math.sign(x)
|
function math.sign(x)
|
||||||
if x<0 then
|
if x < 0 then
|
||||||
return -1
|
return -1
|
||||||
elseif x>0 then
|
elseif x > 0 then
|
||||||
return 1
|
return 1
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local math_sign = math.sign
|
local math_sign = math.sign
|
||||||
@ -96,8 +95,8 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
|
|||||||
self.ashearY = shearY
|
self.ashearY = shearY
|
||||||
self.appliedValid = true
|
self.appliedValid = true
|
||||||
|
|
||||||
local sx = self.skeleton.scaleX;
|
local sx = self.skeleton.scaleX
|
||||||
local sy = self.skeleton.scaleY;
|
local sy = self.skeleton.scaleY
|
||||||
|
|
||||||
local parent = self.parent
|
local parent = self.parent
|
||||||
if parent == nil then
|
if parent == nil then
|
||||||
@ -132,7 +131,7 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
|
|||||||
self.b = pa * lb + pb * ld
|
self.b = pa * lb + pb * ld
|
||||||
self.c = pc * la + pd * lc
|
self.c = pc * la + pd * lc
|
||||||
self.d = pc * lb + pd * ld
|
self.d = pc * lb + pd * ld
|
||||||
return;
|
return
|
||||||
elseif transformMode == TransformMode.onlyTranslation then
|
elseif transformMode == TransformMode.onlyTranslation then
|
||||||
local rotationY = rotation + 90 + shearY
|
local rotationY = rotation + 90 + shearY
|
||||||
self.a = math_cos(math_rad(rotation + shearX)) * scaleX
|
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
|
pc = pc / self.skeleton.scaleY
|
||||||
pb = pc * s
|
pb = pc * s
|
||||||
pd = pa * s
|
pd = pa * s
|
||||||
prx = math_deg(math_atan2(pc, pa));
|
prx = math_deg(math_atan2(pc, pa))
|
||||||
else
|
else
|
||||||
pa = 0;
|
pa = 0
|
||||||
pc = 0;
|
pc = 0
|
||||||
prx = 90 - math_deg(math_atan2(pd, pb));
|
prx = 90 - math_deg(math_atan2(pd, pb))
|
||||||
end
|
end
|
||||||
local rx = rotation + shearX - prx
|
local rx = rotation + shearX - prx
|
||||||
local ry = rotation + shearY - prx + 90
|
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 r = math_pi / 2 + math_atan2(zc, za)
|
||||||
local zb = math_cos(r) * s
|
local zb = math_cos(r) * s
|
||||||
local zd = math_sin(r) * s
|
local zd = math_sin(r) * s
|
||||||
local la = math_cos(math_rad(shearX)) * scaleX;
|
local la = math_cos(math_rad(shearX)) * scaleX
|
||||||
local lb = math_cos(math_rad(90 + shearY)) * scaleY;
|
local lb = math_cos(math_rad(90 + shearY)) * scaleY
|
||||||
local lc = math_sin(math_rad(shearX)) * scaleX;
|
local lc = math_sin(math_rad(shearX)) * scaleX
|
||||||
local ld = math_sin(math_rad(90 + shearY)) * scaleY;
|
local ld = math_sin(math_rad(90 + shearY)) * scaleY
|
||||||
self.a = za * la + zb * lc
|
self.a = za * la + zb * lc
|
||||||
self.b = za * lb + zb * ld
|
self.b = za * lb + zb * ld
|
||||||
self.c = zc * la + zd * lc
|
self.c = zc * la + zd * lc
|
||||||
|
|||||||
@ -47,7 +47,8 @@ function BoneData.new (index, name, parent)
|
|||||||
shearX = 0, shearY = 0,
|
shearX = 0, shearY = 0,
|
||||||
inheritRotation = true,
|
inheritRotation = true,
|
||||||
inheritScale = true,
|
inheritScale = true,
|
||||||
skinRequired = false
|
skinRequired = false,
|
||||||
|
color = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return self
|
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
|
tx = targetX - bone.worldX
|
||||||
ty = targetY - bone.worldY
|
ty = targetY - bone.worldY
|
||||||
elseif bone.data.transformMode == TransformMode.noRotationOrReflection then
|
elseif bone.data.transformMode == TransformMode.noRotationOrReflection then
|
||||||
local s = math_abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
local s = math_abs(pa * pd - pb * pc) / (pa * pa + pc * pc)
|
||||||
local sa = pa / bone.skeleton.scaleX;
|
local sa = pa / bone.skeleton.scaleX
|
||||||
local sc = pc / bone.skeleton.scaleY;
|
local sc = pc / bone.skeleton.scaleY
|
||||||
pb = -sc * s * bone.skeleton.scaleX;
|
pb = -sc * s * bone.skeleton.scaleX
|
||||||
pd = sa * s * bone.skeleton.scaleY;
|
pd = sa * s * bone.skeleton.scaleY
|
||||||
rotationIK = rotationIK + math_deg(math_atan2(sc, sa));
|
rotationIK = rotationIK + math_deg(math_atan2(sc, sa))
|
||||||
|
|
||||||
|
|
||||||
local x = targetX - p.worldX
|
local x = targetX - p.worldX
|
||||||
@ -255,13 +255,13 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
|
|||||||
b = psy * l2
|
b = psy * l2
|
||||||
local aa = a * a
|
local aa = a * a
|
||||||
local bb = b * b
|
local bb = b * b
|
||||||
local ta = math_atan2(ty, tx);
|
local ta = math_atan2(ty, tx)
|
||||||
c = bb * l1 * l1 + aa * dd - aa * bb
|
c = bb * l1 * l1 + aa * dd - aa * bb
|
||||||
local c1 = -2 * bb * l1
|
local c1 = -2 * bb * l1
|
||||||
local c2 = bb - aa
|
local c2 = bb - aa
|
||||||
d = c1 * c1 - 4 * c2 * c
|
d = c1 * c1 - 4 * c2 * c
|
||||||
if d >= 0 then
|
if d >= 0 then
|
||||||
local q = math_sqrt(d);
|
local q = math_sqrt(d)
|
||||||
if (c1 < 0) then q = -q end
|
if (c1 < 0) then q = -q end
|
||||||
q = -(c1 + q) / 2
|
q = -(c1 + q) / 2
|
||||||
local r0 = q / c2
|
local r0 = q / c2
|
||||||
@ -279,7 +279,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
|
|||||||
local minAngle = math_pi
|
local minAngle = math_pi
|
||||||
local minX = l1 - a
|
local minX = l1 - a
|
||||||
local minDist = minX * minX
|
local minDist = minX * minX
|
||||||
local minY = 0;
|
local minY = 0
|
||||||
local maxAngle = 0
|
local maxAngle = 0
|
||||||
local maxX = l1 + a
|
local maxX = l1 + a
|
||||||
local maxDist = maxX * maxX
|
local maxDist = maxX * maxX
|
||||||
@ -328,7 +328,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch,
|
|||||||
elseif a2 < -180 then
|
elseif a2 < -180 then
|
||||||
a2 = a2 + 360
|
a2 = a2 + 360
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
return IkConstraint
|
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
|
local rotate = rotateMix > 0
|
||||||
if not translate and not rotate then return end
|
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 percentSpacing = data.spacingMode == PathConstraintData.SpacingMode.percent
|
||||||
local rotateMode = data.rotateMode
|
local rotateMode = data.rotateMode
|
||||||
local tangents = rotateMode == PathConstraintData.RotateMode.tangent
|
local tangents = rotateMode == PathConstraintData.RotateMode.tangent
|
||||||
@ -117,7 +117,7 @@ function PathConstraint:update ()
|
|||||||
local i = 0
|
local i = 0
|
||||||
local n = spacesCount - 1
|
local n = spacesCount - 1
|
||||||
while i < n do
|
while i < n do
|
||||||
local bone = bones[i + 1];
|
local bone = bones[i + 1]
|
||||||
local setupLength = bone.data.length
|
local setupLength = bone.data.length
|
||||||
if setupLength < PathConstraint.epsilon then
|
if setupLength < PathConstraint.epsilon then
|
||||||
if scale then lengths[i + 1] = 0 end
|
if scale then lengths[i + 1] = 0 end
|
||||||
@ -157,12 +157,12 @@ function PathConstraint:update ()
|
|||||||
local boneX = positions[1]
|
local boneX = positions[1]
|
||||||
local boneY = positions[2]
|
local boneY = positions[2]
|
||||||
local offsetRotation = data.offsetRotation
|
local offsetRotation = data.offsetRotation
|
||||||
local tip = false;
|
local tip = false
|
||||||
if offsetRotation == 0 then
|
if offsetRotation == 0 then
|
||||||
tip = rotateMode == PathConstraintData.RotateMode.chain
|
tip = rotateMode == PathConstraintData.RotateMode.chain
|
||||||
else
|
else
|
||||||
tip = false;
|
tip = false
|
||||||
local p = self.target.bone;
|
local p = self.target.bone
|
||||||
if p.a * p.d - p.b * p.c > 0 then
|
if p.a * p.d - p.b * p.c > 0 then
|
||||||
offsetRotation = offsetRotation * utils.degRad
|
offsetRotation = offsetRotation * utils.degRad
|
||||||
else
|
else
|
||||||
@ -210,8 +210,8 @@ function PathConstraint:update ()
|
|||||||
cos = math_cos(r)
|
cos = math_cos(r)
|
||||||
sin = math_sin(r)
|
sin = math_sin(r)
|
||||||
local length = bone.data.length
|
local length = bone.data.length
|
||||||
boneX = boneX + (length * (cos * a - sin * c) - dx) * rotateMix;
|
boneX = boneX + (length * (cos * a - sin * c) - dx) * rotateMix
|
||||||
boneY = boneY + (length * (sin * a + cos * c) - dy) * rotateMix;
|
boneY = boneY + (length * (sin * a + cos * c) - dy) * rotateMix
|
||||||
else
|
else
|
||||||
r = r + offsetRotation
|
r = r + offsetRotation
|
||||||
end
|
end
|
||||||
@ -249,7 +249,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
|||||||
if not path.constantSpeed then
|
if not path.constantSpeed then
|
||||||
local lengths = path.lengths
|
local lengths = path.lengths
|
||||||
if closed then curveCount = curveCount - 1 else curveCount = curveCount - 2 end
|
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 percentPosition then position = position * pathLength end
|
||||||
if percentSpacing then
|
if percentSpacing then
|
||||||
i = 1
|
i = 1
|
||||||
@ -258,12 +258,12 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
|||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
world = utils.setArraySize(self.world, 8);
|
world = utils.setArraySize(self.world, 8)
|
||||||
i = 0
|
i = 0
|
||||||
local o = 0
|
local o = 0
|
||||||
local curve = 0
|
local curve = 0
|
||||||
while i < spacesCount do
|
while i < spacesCount do
|
||||||
local space = spaces[i + 1];
|
local space = spaces[i + 1]
|
||||||
position = position + space
|
position = position + space
|
||||||
local p = position
|
local p = position
|
||||||
|
|
||||||
@ -331,14 +331,14 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
|||||||
world[verticesLength - 1 + 1] = world[1 + 1]
|
world[verticesLength - 1 + 1] = world[1 + 1]
|
||||||
else
|
else
|
||||||
curveCount = curveCount - 1
|
curveCount = curveCount - 1
|
||||||
verticesLength = verticesLength - 4;
|
verticesLength = verticesLength - 4
|
||||||
world = utils.setArraySize(self.world, verticesLength)
|
world = utils.setArraySize(self.world, verticesLength)
|
||||||
path:computeWorldVertices(target, 2, verticesLength, world, 0, 2)
|
path:computeWorldVertices(target, 2, verticesLength, world, 0, 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Curve lengths.
|
-- Curve lengths.
|
||||||
local curves = utils.setArraySize(self.curves, curveCount)
|
local curves = utils.setArraySize(self.curves, curveCount)
|
||||||
local pathLength = 0;
|
local pathLength = 0
|
||||||
local x1 = world[0 + 1]
|
local x1 = world[0 + 1]
|
||||||
local y1 = world[1 + 1]
|
local y1 = world[1 + 1]
|
||||||
local cx1 = 0
|
local cx1 = 0
|
||||||
@ -392,7 +392,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
|||||||
if percentPosition then
|
if percentPosition then
|
||||||
position = position * pathLength
|
position = position * pathLength
|
||||||
else
|
else
|
||||||
position = position * pathLength / path.lengths[curveCount];
|
position = position * pathLength / path.lengths[curveCount]
|
||||||
end
|
end
|
||||||
if percentSpacing then
|
if percentSpacing then
|
||||||
i = 1
|
i = 1
|
||||||
@ -496,7 +496,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
|||||||
local prev = segments[segment - 1 + 1]
|
local prev = segments[segment - 1 + 1]
|
||||||
p = segment + (p - prev) / (length - prev)
|
p = segment + (p - prev) / (length - prev)
|
||||||
end
|
end
|
||||||
break;
|
break
|
||||||
end
|
end
|
||||||
segment = segment + 1
|
segment = segment + 1
|
||||||
end
|
end
|
||||||
@ -536,7 +536,7 @@ function PathConstraint:addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2,
|
|||||||
out[o + 1] = x1
|
out[o + 1] = x1
|
||||||
out[o + 2] = y1
|
out[o + 2] = y1
|
||||||
out[o + 3] = math_atan2(cy1 - y1, cx1 - x1)
|
out[o + 3] = math_atan2(cy1 - y1, cx1 - x1)
|
||||||
return;
|
return
|
||||||
end
|
end
|
||||||
local tt = p * p
|
local tt = p * p
|
||||||
local ttt = tt * 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
|
end
|
||||||
|
|
||||||
function Skeleton:getAttachment (slotName, attachmentName)
|
function Skeleton:getAttachment (slotName, attachmentName)
|
||||||
return self:getAttachmentByIndex(self.data.slotNameIndices[slotName], attachmentName)
|
return self:getAttachmentByIndex(self.data.nameToSlot[slotName].index, attachmentName)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Skeleton:getAttachmentByIndex (slotIndex, attachmentName)
|
function Skeleton:getAttachmentByIndex (slotIndex, attachmentName)
|
||||||
@ -520,7 +520,7 @@ end
|
|||||||
function Skeleton:getBounds(offset, size)
|
function Skeleton:getBounds(offset, size)
|
||||||
if not offset then error("offset cannot be null.", 2) end
|
if not offset then error("offset cannot be null.", 2) end
|
||||||
if not size then error("size 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 minX = 99999999
|
||||||
local minY = 99999999
|
local minY = 99999999
|
||||||
local maxX = -99999999
|
local maxX = -99999999
|
||||||
|
|||||||
@ -118,7 +118,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
|
|||||||
local u2 = uvs[vertexOffset]
|
local u2 = uvs[vertexOffset]
|
||||||
local v2 = uvs[vertexOffset + 1]
|
local v2 = uvs[vertexOffset + 1]
|
||||||
|
|
||||||
vertexOffset = (triangles[i + 2] - 1) * 2 + 1;
|
vertexOffset = (triangles[i + 2] - 1) * 2 + 1
|
||||||
local x3 = vertices[vertexOffset]
|
local x3 = vertices[vertexOffset]
|
||||||
local y3 = vertices[vertexOffset + 1]
|
local y3 = vertices[vertexOffset + 1]
|
||||||
local u3 = uvs[vertexOffset]
|
local u3 = uvs[vertexOffset]
|
||||||
@ -135,7 +135,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
|
|||||||
local d1 = x3 - x2
|
local d1 = x3 - x2
|
||||||
local d2 = x1 - x3
|
local d2 = x1 - x3
|
||||||
local d4 = y3 - y1
|
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 clipOutputCount = clipOutputLength / 2
|
||||||
local clipOutputItems = clipOutput
|
local clipOutputItems = clipOutput
|
||||||
@ -193,7 +193,7 @@ function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLengt
|
|||||||
clippedTrianglesItems[s] = index
|
clippedTrianglesItems[s] = index
|
||||||
clippedTrianglesItems[s + 1] = index + 1
|
clippedTrianglesItems[s + 1] = index + 1
|
||||||
clippedTrianglesItems[s + 2] = index + 2
|
clippedTrianglesItems[s + 2] = index + 2
|
||||||
index = index + 3;
|
index = index + 3
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
p = p + 1
|
p = p + 1
|
||||||
@ -246,7 +246,7 @@ function SkeletonClipping:clip(x1, y1, x2, y2, x3, y3, clippingArea, output)
|
|||||||
local inputX2 = inputVertices[ii + 2]
|
local inputX2 = inputVertices[ii + 2]
|
||||||
local inputY2 = inputVertices[ii + 3]
|
local inputY2 = inputVertices[ii + 3]
|
||||||
local side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0
|
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 deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0 then
|
||||||
if side2 then -- v1 inside, v2 inside
|
if side2 then -- v1 inside, v2 inside
|
||||||
table_insert(output, inputX2)
|
table_insert(output, inputX2)
|
||||||
|
|||||||
@ -37,6 +37,7 @@ function SkeletonData.new ()
|
|||||||
name,
|
name,
|
||||||
bones = {},
|
bones = {},
|
||||||
slots = {},
|
slots = {},
|
||||||
|
nameToSlot = {},
|
||||||
skins = {},
|
skins = {},
|
||||||
defaultSkin = nil,
|
defaultSkin = nil,
|
||||||
events = {},
|
events = {},
|
||||||
@ -45,8 +46,7 @@ function SkeletonData.new ()
|
|||||||
transformConstraints = {},
|
transformConstraints = {},
|
||||||
pathConstraints = {},
|
pathConstraints = {},
|
||||||
x, y, width, height,
|
x, y, width, height,
|
||||||
version, hash, imagesPath,
|
version, hash, imagesPath
|
||||||
slotNameIndices = {}
|
|
||||||
}
|
}
|
||||||
setmetatable(self, SkeletonData)
|
setmetatable(self, SkeletonData)
|
||||||
|
|
||||||
@ -71,15 +71,7 @@ end
|
|||||||
|
|
||||||
function SkeletonData:findSlot (slotName)
|
function SkeletonData:findSlot (slotName)
|
||||||
if not slotName then error("slotName cannot be nil.", 2) end
|
if not slotName then error("slotName cannot be nil.", 2) end
|
||||||
for i,slot in ipairs(self.slots) do
|
return self.nameToSlot[slotName]
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function SkeletonData:findSkin (skinName)
|
function SkeletonData:findSkin (skinName)
|
||||||
@ -130,12 +122,4 @@ function SkeletonData:findPathConstraint (constraintName)
|
|||||||
return nil
|
return nil
|
||||||
end
|
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
|
return SkeletonData
|
||||||
|
|||||||
@ -65,6 +65,8 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
local readAttachment
|
local readAttachment
|
||||||
local readAnimation
|
local readAnimation
|
||||||
local readCurve
|
local readCurve
|
||||||
|
local readTimeline1
|
||||||
|
local readTimeline2
|
||||||
local getArray
|
local getArray
|
||||||
|
|
||||||
local getValue = function (map, name, default)
|
local getValue = function (map, name, default)
|
||||||
@ -83,9 +85,6 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
if skeletonMap then
|
if skeletonMap then
|
||||||
skeletonData.hash = skeletonMap["hash"]
|
skeletonData.hash = skeletonMap["hash"]
|
||||||
skeletonData.version = skeletonMap["spine"]
|
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.x = skeletonMap["x"]
|
||||||
skeletonData.y = skeletonMap["y"]
|
skeletonData.y = skeletonMap["y"]
|
||||||
skeletonData.width = skeletonMap["width"]
|
skeletonData.width = skeletonMap["width"]
|
||||||
@ -105,17 +104,25 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
if not parent then error("Parent bone not found: " .. parentName) end
|
if not parent then error("Parent bone not found: " .. parentName) end
|
||||||
end
|
end
|
||||||
local data = BoneData.new(i, boneName, parent)
|
local data = BoneData.new(i, boneName, parent)
|
||||||
data.length = getValue(boneMap, "length", 0) * scale;
|
data.length = getValue(boneMap, "length", 0) * scale
|
||||||
data.x = getValue(boneMap, "x", 0) * scale;
|
data.x = getValue(boneMap, "x", 0) * scale
|
||||||
data.y = getValue(boneMap, "y", 0) * scale;
|
data.y = getValue(boneMap, "y", 0) * scale
|
||||||
data.rotation = getValue(boneMap, "rotation", 0);
|
data.rotation = getValue(boneMap, "rotation", 0)
|
||||||
data.scaleX = getValue(boneMap, "scaleX", 1);
|
data.scaleX = getValue(boneMap, "scaleX", 1)
|
||||||
data.scaleY = getValue(boneMap, "scaleY", 1);
|
data.scaleY = getValue(boneMap, "scaleY", 1)
|
||||||
data.shearX = getValue(boneMap, "shearX", 0);
|
data.shearX = getValue(boneMap, "shearX", 0)
|
||||||
data.shearY = getValue(boneMap, "shearY", 0);
|
data.shearY = getValue(boneMap, "shearY", 0)
|
||||||
data.transformMode = TransformMode[getValue(boneMap, "transform", "normal")]
|
data.transformMode = TransformMode[getValue(boneMap, "transform", "normal")]
|
||||||
data.skinRequired = getValue(boneMap, "skin", false)
|
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)
|
table_insert(skeletonData.bones, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -138,18 +145,17 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
|
|
||||||
local dark = slotMap["dark"]
|
local dark = slotMap["dark"]
|
||||||
if dark then
|
if dark then
|
||||||
data.darkColor = Color.newWith(1, 1, 1, 1)
|
data.darkColor = Color.newWith(
|
||||||
data.darkColor:set(tonumber(dark:sub(1, 2), 16) / 255,
|
tonumber(dark:sub(1, 2), 16) / 255,
|
||||||
tonumber(dark:sub(3, 4), 16) / 255,
|
tonumber(dark:sub(3, 4), 16) / 255,
|
||||||
tonumber(dark:sub(5, 6), 16) / 255,
|
tonumber(dark:sub(5, 6), 16) / 255, 0)
|
||||||
0)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
data.attachmentName = getValue(slotMap, "attachment", nil)
|
data.attachmentName = getValue(slotMap, "attachment", nil)
|
||||||
data.blendMode = BlendMode[getValue(slotMap, "blend", "normal")]
|
data.blendMode = BlendMode[getValue(slotMap, "blend", "normal")]
|
||||||
|
|
||||||
table_insert(skeletonData.slots, data)
|
table_insert(skeletonData.slots, data)
|
||||||
skeletonData.slotNameIndices[data.name] = #skeletonData.slots
|
skeletonData.nameToSlot[data.name] = data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -204,17 +210,19 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
|
|
||||||
data.local_ = getValue(constraintMap, "local", false)
|
data.local_ = getValue(constraintMap, "local", false)
|
||||||
data.relative = getValue(constraintMap, "relative", false)
|
data.relative = getValue(constraintMap, "relative", false)
|
||||||
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
data.offsetRotation = getValue(constraintMap, "rotation", 0)
|
||||||
data.offsetX = getValue(constraintMap, "x", 0) * scale;
|
data.offsetX = getValue(constraintMap, "x", 0) * scale
|
||||||
data.offsetY = getValue(constraintMap, "y", 0) * scale;
|
data.offsetY = getValue(constraintMap, "y", 0) * scale
|
||||||
data.offsetScaleX = getValue(constraintMap, "scaleX", 0);
|
data.offsetScaleX = getValue(constraintMap, "scaleX", 0)
|
||||||
data.offsetScaleY = getValue(constraintMap, "scaleY", 0);
|
data.offsetScaleY = getValue(constraintMap, "scaleY", 0)
|
||||||
data.offsetShearY = getValue(constraintMap, "shearY", 0);
|
data.offsetShearY = getValue(constraintMap, "shearY", 0)
|
||||||
|
|
||||||
data.rotateMix = getValue(constraintMap, "rotateMix", 1);
|
data.mixRotate = getValue(constraintMap, "rotateMix", 1)
|
||||||
data.translateMix = getValue(constraintMap, "translateMix", 1);
|
data.mixX = getValue(constraintMap, "mixX", 1)
|
||||||
data.scaleMix = getValue(constraintMap, "scaleMix", 1);
|
data.mixY = getValue(constraintMap, "mixY", data.mixX)
|
||||||
data.shearMix = getValue(constraintMap, "shearMix", 1);
|
data.mixScaleX = getValue(constraintMap, "mixScaleX", 1)
|
||||||
|
data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX)
|
||||||
|
data.mixShearY = getValue(constraintMap, "mixShearY", 1)
|
||||||
|
|
||||||
table_insert(skeletonData.transformConstraints, data)
|
table_insert(skeletonData.transformConstraints, data)
|
||||||
end
|
end
|
||||||
@ -222,8 +230,8 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
|
|
||||||
-- Path constraints
|
-- Path constraints
|
||||||
if root["path"] then
|
if root["path"] then
|
||||||
for _,constraintMap in ipairs(root.path) do
|
for _,constraintMap in ipairs(root["path"]) do
|
||||||
local data = PathConstraintData.new(constraintMap.name);
|
local data = PathConstraintData.new(constraintMap.name)
|
||||||
data.order = getValue(constraintMap, "order", 0)
|
data.order = getValue(constraintMap, "order", 0)
|
||||||
data.skinRequired = getValue(constraintMap, "skin", false)
|
data.skinRequired = getValue(constraintMap, "skin", false)
|
||||||
|
|
||||||
@ -233,20 +241,21 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
table_insert(data.bones, bone)
|
table_insert(data.bones, bone)
|
||||||
end
|
end
|
||||||
|
|
||||||
local targetName = constraintMap.target;
|
local targetName = constraintMap.target
|
||||||
data.target = skeletonData:findSlot(targetName)
|
data.target = skeletonData:findSlot(targetName)
|
||||||
if data.target == nil then error("Path target slot not found: " .. targetName, 2) end
|
if data.target == nil then error("Path target slot not found: " .. targetName, 2) end
|
||||||
|
|
||||||
data.positionMode = PathConstraintData.PositionMode[getValue(constraintMap, "positionMode", "percent"):lower()]
|
data.positionMode = PathConstraintData.PositionMode[getValue(constraintMap, "positionMode", "percent"):lower()]
|
||||||
data.spacingMode = PathConstraintData.SpacingMode[getValue(constraintMap, "spacingMode", "length"):lower()]
|
data.spacingMode = PathConstraintData.SpacingMode[getValue(constraintMap, "spacingMode", "length"):lower()]
|
||||||
data.rotateMode = PathConstraintData.RotateMode[getValue(constraintMap, "rotateMode", "tangent"):lower()]
|
data.rotateMode = PathConstraintData.RotateMode[getValue(constraintMap, "rotateMode", "tangent"):lower()]
|
||||||
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
data.offsetRotation = getValue(constraintMap, "rotation", 0)
|
||||||
data.position = getValue(constraintMap, "position", 0);
|
data.position = getValue(constraintMap, "position", 0)
|
||||||
if data.positionMode == PathConstraintData.PositionMode.fixed then data.position = data.position * scale end
|
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
|
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.mixRotate = getValue(constraintMap, "mixRotate", 1)
|
||||||
data.translateMix = getValue(constraintMap, "translateMix", 1);
|
data.mixX = getValue(constraintMap, "mixX", 1)
|
||||||
|
data.mixY = getValue(constraintMap, "mixY", data.mixX)
|
||||||
|
|
||||||
table_insert(skeletonData.pathConstraints, data)
|
table_insert(skeletonData.pathConstraints, data)
|
||||||
end
|
end
|
||||||
@ -290,7 +299,7 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for slotName,slotMap in pairs(skinMap.attachments) do
|
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
|
for attachmentName,attachmentMap in pairs(slotMap) do
|
||||||
local attachment = readAttachment(attachmentMap, skin, slotIndex, attachmentName, skeletonData)
|
local attachment = readAttachment(attachmentMap, skin, slotIndex, attachmentName, skeletonData)
|
||||||
if attachment then
|
if attachment then
|
||||||
@ -360,11 +369,11 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
region.path = path
|
region.path = path
|
||||||
region.x = getValue(map, "x", 0) * scale
|
region.x = getValue(map, "x", 0) * scale
|
||||||
region.y = getValue(map, "y", 0) * scale
|
region.y = getValue(map, "y", 0) * scale
|
||||||
region.scaleX = getValue(map, "scaleX", 1);
|
region.scaleX = getValue(map, "scaleX", 1)
|
||||||
region.scaleY = getValue(map, "scaleY", 1);
|
region.scaleY = getValue(map, "scaleY", 1)
|
||||||
region.rotation = getValue(map, "rotation", 0);
|
region.rotation = getValue(map, "rotation", 0)
|
||||||
region.width = map.width * scale;
|
region.width = map.width * scale
|
||||||
region.height = map.height * scale;
|
region.height = map.height * scale
|
||||||
|
|
||||||
local color = map["color"]
|
local color = map["color"]
|
||||||
if color then
|
if color then
|
||||||
@ -453,7 +462,7 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
tonumber(color:sub(5, 6), 16) / 255,
|
tonumber(color:sub(5, 6), 16) / 255,
|
||||||
tonumber(color:sub(7, 8), 16) / 255)
|
tonumber(color:sub(7, 8), 16) / 255)
|
||||||
end
|
end
|
||||||
return path;
|
return path
|
||||||
|
|
||||||
elseif type == AttachmentType.point then
|
elseif type == AttachmentType.point then
|
||||||
local point = self.attachmentLoader:newPointAttachment(skin, name)
|
local point = self.attachmentLoader:newPointAttachment(skin, name)
|
||||||
@ -536,124 +545,239 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
|
|
||||||
readAnimation = function (map, name, skeletonData)
|
readAnimation = function (map, name, skeletonData)
|
||||||
local timelines = {}
|
local timelines = {}
|
||||||
local duration = 0
|
|
||||||
local scale = self.scale
|
local scale = self.scale
|
||||||
|
|
||||||
-- Slot timelines
|
-- Slot timelines.
|
||||||
local slotsMap = map["slots"]
|
local slotsMap = map["slots"]
|
||||||
if slotsMap then
|
if slotsMap then
|
||||||
for slotName,timelineMap in pairs(slotsMap) do
|
for slotName,slotMap in pairs(slotsMap) do
|
||||||
local slotIndex = skeletonData.slotNameIndices[slotName]
|
local slotIndex = skeletonData:findSlot(slotName).index
|
||||||
|
for timelineName,timelineMap in pairs(slotMap) do
|
||||||
for timelineName,values in pairs(timelineMap) do
|
if not timelineMap then
|
||||||
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])
|
|
||||||
elseif timelineName == "attachment" then
|
elseif timelineName == "attachment" then
|
||||||
local timeline = Animation.AttachmentTimeline.new(#values)
|
local timeline = Animation.AttachmentTimeline.new(#timelineMap, slotIndex)
|
||||||
timeline.slotIndex = slotIndex
|
for i,keyMap in ipairs(timelineMap) do
|
||||||
|
timeline:setFrame(i + 1, getValue(keyMap, "time", 0), keyMap["name"])
|
||||||
local frameIndex = 0
|
end
|
||||||
for _,valueMap in ipairs(values) do
|
table_insert(timelines, timeline)
|
||||||
local attachmentName = valueMap["name"]
|
elseif timelineName == "rgba" then
|
||||||
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), attachmentName)
|
local timeline = Animation.RGBATimeline.new(#timelineMap, #timelineMap * 4, slotIndex)
|
||||||
frameIndex = frameIndex + 1
|
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
|
end
|
||||||
table_insert(timelines, timeline)
|
table_insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
|
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Invalid frame type for a slot: " .. timelineName .. " (" .. slotName .. ")")
|
error("Invalid timeline type for a slot: " .. timelineName .. " (" .. slotName .. ")")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Bone timelines
|
-- Bone timelines.
|
||||||
local bonesMap = map["bones"]
|
local bonesMap = map["bones"]
|
||||||
if bonesMap then
|
if bonesMap then
|
||||||
for boneName,timelineMap in pairs(bonesMap) do
|
for boneName,boneMap in pairs(bonesMap) do
|
||||||
local boneIndex = skeletonData:findBoneIndex(boneName)
|
local boneIndex = skeletonData:findBoneIndex(boneName)
|
||||||
if boneIndex == -1 then error("Bone not found: " .. boneName) end
|
if boneIndex == -1 then error("Bone not found: " .. boneName) end
|
||||||
|
for timelineName,timelineMap in pairs(boneMap) do
|
||||||
for timelineName,values in pairs(timelineMap) do
|
if not timelineMap then
|
||||||
if timelineName == "rotate" then
|
elseif timelineName == "rotate" then
|
||||||
local timeline = Animation.RotateTimeline.new(#values)
|
table_insert(timelines, readTimeline1(timelineMap, Animation.RotateTimeline.new(#timelineMap, #timelineMap, boneIndex), 0, 1))
|
||||||
timeline.boneIndex = boneIndex
|
elseif timelineName == "translate" then
|
||||||
|
local timeline = Animation.TranslateTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
|
||||||
local frameIndex = 0
|
table_insert(timelines, readTimeline2(timelineMap, timeline, "x", "y", 0, scale))
|
||||||
for _,valueMap in ipairs(values) do
|
elseif timelineName == "translatex" then
|
||||||
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "angle", 0))
|
local timeline = Animation.TranslateXTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
readCurve(valueMap, timeline, frameIndex)
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, scale))
|
||||||
frameIndex = frameIndex + 1
|
elseif timelineName == "translatey" then
|
||||||
end
|
local timeline = Animation.TranslateYTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
table_insert(timelines, timeline)
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, scale))
|
||||||
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.RotateTimeline.ENTRIES])
|
elseif timelineName == "scale" then
|
||||||
|
local timeline = Animation.ScaleTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
|
||||||
elseif timelineName == "translate" or timelineName == "scale" or timelineName == "shear" then
|
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 1, 1))
|
||||||
local timeline
|
elseif timelineName == "scalex" then
|
||||||
local timelineScale = 1
|
local timeline = Animation.ScaleXTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
local defaultValue = 0
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
|
||||||
if timelineName == "scale" then
|
elseif timelineName == "scaley" then
|
||||||
timeline = Animation.ScaleTimeline.new(#values)
|
local timeline = Animation.ScaleYTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
defaultValue = 1
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
|
||||||
elseif timelineName == "shear" then
|
elseif timelineName == "shear" then
|
||||||
timeline = Animation.ShearTimeline.new(#values)
|
local timeline = Animation.ShearTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
|
||||||
else
|
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 0, 1))
|
||||||
timeline = Animation.TranslateTimeline.new(#values)
|
elseif timelineName == "shearx" then
|
||||||
timelineScale = self.scale
|
local timeline = Animation.ShearXTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
end
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, 1))
|
||||||
timeline.boneIndex = boneIndex
|
elseif timelineName == "sheary" then
|
||||||
|
local timeline = Animation.ShearYTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||||
local frameIndex = 0
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, 1))
|
||||||
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])
|
|
||||||
else
|
else
|
||||||
error("Invalid timeline type for a bone: " .. timelineName .. " (" .. boneName .. ")")
|
error("Invalid timeline type for a bone: " .. timelineName .. " (" .. boneName .. ")")
|
||||||
end
|
end
|
||||||
@ -664,96 +788,169 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
-- IK timelines.
|
-- IK timelines.
|
||||||
local ik = map["ik"]
|
local ik = map["ik"]
|
||||||
if ik then
|
if ik then
|
||||||
for ikConstraintName,values in pairs(ik) do
|
for constraintName,timelineMap in pairs(ik) do
|
||||||
local ikConstraint = skeletonData:findIkConstraint(ikConstraintName)
|
local keyMap = timelineMap[1]
|
||||||
local timeline = Animation.IkConstraintTimeline.new(#values)
|
if keyMap then
|
||||||
for i,other in pairs(skeletonData.ikConstraints) do
|
local constraintIndex = -1
|
||||||
if other == ikConstraint then
|
for i,other in pairs(skeletonData.ikConstraints) do
|
||||||
timeline.ikConstraintIndex = i
|
if other.name == constraintName then
|
||||||
break
|
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
|
||||||
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)
|
table_insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline.frames[(timeline:getFrameCount() - 1) * Animation.IkConstraintTimeline.ENTRIES])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Transform constraint timelines.
|
-- Transform constraint timelines.
|
||||||
local transform = map["transform"]
|
local transform = map["transform"]
|
||||||
if transform then
|
if transform then
|
||||||
for constraintName, values in pairs(transform) do
|
for constraintName, timelineMap in pairs(transform) do
|
||||||
local constraint = skeletonData:findTransformConstraint(constraintName)
|
local keyMap = timelineMap[1]
|
||||||
local timeline = Animation.TransformConstraintTimeline.new(#values)
|
if keyMap then
|
||||||
for i,other in pairs(skeletonData.transformConstraints) do
|
local constraintIndex = -1
|
||||||
if other == constraint then
|
for i,other in pairs(skeletonData.transformConstraints) do
|
||||||
timeline.transformConstraintIndex = i
|
if other.name == constraintName then
|
||||||
break
|
constraintIndex = i
|
||||||
|
break
|
||||||
|
end
|
||||||
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Path constraint timelines.
|
-- Path constraint timelines.
|
||||||
if map.path then
|
if map.path then
|
||||||
for constraintName,constraintMap in pairs(map.path) do
|
for constraintName,constraintMap in pairs(map.path) do
|
||||||
local index = skeletonData:findPathConstraintIndex(constraintName)
|
local constraint, constraintIndex = -1
|
||||||
if index == -1 then error("Path constraint not found: " .. constraintName, 2) end
|
for i,other in pairs(skeletonData.transformConstraints) do
|
||||||
local data = skeletonData.pathConstraints[index]
|
if other.name == constraintName then
|
||||||
|
constraintIndex = i
|
||||||
|
constraint = other
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
for timelineName, timelineMap in pairs(constraintMap) do
|
for timelineName, timelineMap in pairs(constraintMap) do
|
||||||
if timelineName == "position" or timelineName == "spacing" then
|
local keyMap = timelineMap[1]
|
||||||
local timeline = nil
|
if keyMap then
|
||||||
local timelineScale = 1
|
if timelineName == "position" then
|
||||||
if timelineName == "spacing" then
|
local timeline = Animation.PathConstraintPositionTimeline.new(#timelineMap, #timelineMap, constraintIndex)
|
||||||
timeline = Animation.PathConstraintSpacingTimeline.new(#timelineMap)
|
local timelineScale = 1
|
||||||
if data.spacingMode == PathConstraintData.SpacingMode.length or data.spacingMode == PathConstraintData.SpacingMode.fixed then timelineScale = scale end
|
if constraint.positionMode == PositionMode.fixed then timelineScale = scale end
|
||||||
else
|
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, timelineScale))
|
||||||
timeline = Animation.PathConstraintPositionTimeline.new(#timelineMap)
|
elseif timelineName == "spacing" then
|
||||||
if data.positionMode == PathConstraintData.PositionMode.fixed then timelineScale = scale end
|
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
|
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
|
end
|
||||||
end
|
end
|
||||||
@ -765,68 +962,72 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
local skin = skeletonData:findSkin(deformName)
|
local skin = skeletonData:findSkin(deformName)
|
||||||
if not skin then error("Skin not found: " .. deformName, 2) end
|
if not skin then error("Skin not found: " .. deformName, 2) end
|
||||||
for slotName,slotMap in pairs(deformMap) do
|
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
|
if slotIndex == -1 then error("Slot not found: " .. slotMap.name, 2) end
|
||||||
for timelineName,timelineMap in pairs(slotMap) do
|
for timelineName,timelineMap in pairs(slotMap) do
|
||||||
local attachment = skin:getAttachment(slotIndex, timelineName)
|
local keyMap = timelineMap[1]
|
||||||
if not attachment then error("Deform attachment not found: " .. timelineMap.name, 2) end
|
if keyMap then
|
||||||
local weighted = attachment.bones ~= nil
|
local attachment = skin:getAttachment(slotIndex, timelineName)
|
||||||
local vertices = attachment.vertices;
|
if not attachment then error("Deform attachment not found: " .. timelineMap.name, 2) end
|
||||||
local deformLength = #vertices
|
local weighted = attachment.bones ~= nil
|
||||||
if weighted then deformLength = math.floor(#vertices / 3) * 2 end
|
local vertices = attachment.vertices
|
||||||
|
local deformLength = #vertices
|
||||||
|
if weighted then deformLength = math.floor(deformLength / 3) * 2 end
|
||||||
|
|
||||||
local timeline = Animation.DeformTimeline.new(#timelineMap)
|
local timeline = Animation.DeformTimeline.new(#timelineMap, #timelineMap, slotIndex, attachment)
|
||||||
timeline.slotIndex = slotIndex
|
local bezier = 0
|
||||||
timeline.attachment = attachment
|
for i,keyMap in ipairs(timelineMap) do
|
||||||
|
local deform = nil
|
||||||
local frameIndex = 0
|
local verticesValue = getValue(keyMap, "vertices", nil)
|
||||||
for _,valueMap in ipairs(timelineMap) do
|
if verticesValue == nil then
|
||||||
local deform = nil
|
deform = vertices
|
||||||
local verticesValue = getValue(valueMap, "vertices", nil)
|
if weighted then deform = utils.newNumberArray(deformLength) end
|
||||||
if verticesValue == nil then
|
else
|
||||||
deform = vertices
|
deform = utils.newNumberArray(deformLength)
|
||||||
if weighted then deform = utils.newNumberArray(deformLength) end
|
local start = getValue(keyMap, "offset", 0) + 1
|
||||||
else
|
utils.arrayCopy(verticesValue, 1, deform, start, #verticesValue)
|
||||||
deform = utils.newNumberArray(deformLength)
|
if scale ~= 1 then
|
||||||
local start = getValue(valueMap, "offset", 0) + 1
|
local i = start
|
||||||
utils.arrayCopy(verticesValue, 1, deform, start, #verticesValue)
|
local n = i + #verticesValue
|
||||||
if scale ~= 1 then
|
while i < n do
|
||||||
local i = start
|
deform[i] = deform[i] * scale
|
||||||
local n = i + #verticesValue
|
i = i + 1
|
||||||
while i < n do
|
end
|
||||||
deform[i] = deform[i] * scale
|
end
|
||||||
i = i + 1
|
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
|
||||||
end
|
end
|
||||||
if not weighted then
|
local frame = i - 1
|
||||||
local i = 1
|
timeline:setFrame(frame, time, mixRotate, mixX, mixY)
|
||||||
local n = i + deformLength
|
local nextMap = timelineMap[frame + 1]
|
||||||
while i < n do
|
if not nextMap then
|
||||||
deform[i] = deform[i] + vertices[i]
|
timeline:shrink(bezier)
|
||||||
i = i + 1
|
break
|
||||||
end
|
|
||||||
end
|
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
|
end
|
||||||
|
table_insert(timelines, timeline)
|
||||||
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), deform)
|
|
||||||
readCurve(valueMap, timeline, frameIndex)
|
|
||||||
frameIndex = frameIndex + 1
|
|
||||||
end
|
end
|
||||||
table_insert(timelines, timeline)
|
|
||||||
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Draworder timeline.
|
-- Draw order timelines.
|
||||||
local drawOrderValues = map["drawOrder"]
|
if map["drawOrder"] then
|
||||||
if not drawOrderValues then drawOrderValues = map["draworder"] end
|
local timeline = Animation.DrawOrderTimeline.new(#map["drawOrder"])
|
||||||
if drawOrderValues then
|
|
||||||
local timeline = Animation.DrawOrderTimeline.new(#drawOrderValues)
|
|
||||||
local slotCount = #skeletonData.slots
|
local slotCount = #skeletonData.slots
|
||||||
local frameIndex = 0
|
local frame = 0
|
||||||
for _,drawOrderMap in ipairs(drawOrderValues) do
|
for _,drawOrderMap in ipairs(map["drawOrder"]) do
|
||||||
local drawOrder = nil
|
local drawOrder = nil
|
||||||
local offsets = drawOrderMap["offsets"]
|
local offsets = drawOrderMap["offsets"]
|
||||||
if offsets then
|
if offsets then
|
||||||
@ -835,7 +1036,7 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
local originalIndex = 1
|
local originalIndex = 1
|
||||||
local unchangedIndex = 1
|
local unchangedIndex = 1
|
||||||
for _,offsetMap in ipairs(offsets) do
|
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
|
if slotIndex == -1 then error("Slot not found: " .. offsetMap["slot"]) end
|
||||||
-- Collect unchanged items.
|
-- Collect unchanged items.
|
||||||
while originalIndex ~= slotIndex do
|
while originalIndex ~= slotIndex do
|
||||||
@ -861,18 +1062,17 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
timeline:setFrame(frameIndex, getValue(drawOrderMap, "time", 0), drawOrder)
|
timeline:setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder)
|
||||||
frameIndex = frameIndex + 1
|
frame = frame + 1
|
||||||
end
|
end
|
||||||
table_insert(timelines, timeline)
|
table_insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Event timeline.
|
-- Event timelines.
|
||||||
local events = map["events"]
|
local events = map["events"]
|
||||||
if events then
|
if events then
|
||||||
local timeline = Animation.EventTimeline.new(#events)
|
local timeline = Animation.EventTimeline.new(#events)
|
||||||
local frameIndex = 0
|
local frame = 0
|
||||||
for _,eventMap in ipairs(events) do
|
for _,eventMap in ipairs(events) do
|
||||||
local eventData = skeletonData:findEvent(eventMap["name"])
|
local eventData = skeletonData:findEvent(eventMap["name"])
|
||||||
if not eventData then error("Event not found: " .. eventMap["name"]) end
|
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.volume = getValue(eventMap, "volume", 1)
|
||||||
event.balance = getValue(eventMap, "balance", 0)
|
event.balance = getValue(eventMap, "balance", 0)
|
||||||
end
|
end
|
||||||
timeline:setFrame(frameIndex, event)
|
timeline:setFrame(frame, event)
|
||||||
frameIndex = frameIndex + 1
|
frame = frame + 1
|
||||||
end
|
end
|
||||||
table_insert(timelines, timeline)
|
table_insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline.frames[timeline:getFrameCount() - 1])
|
|
||||||
end
|
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))
|
table_insert(skeletonData.animations, Animation.new(name, timelines, duration))
|
||||||
end
|
end
|
||||||
|
|
||||||
readCurve = function (map, timeline, frameIndex)
|
readCurve = function (map, timeline, frame)
|
||||||
local curve = map["curve"]
|
local curve = map["curve"]
|
||||||
if not curve then return end
|
if not curve then return end
|
||||||
if curve == "stepped" then
|
if curve == "stepped" then
|
||||||
timeline:setStepped(frameIndex)
|
timeline:setStepped(frame)
|
||||||
else
|
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
|
||||||
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)
|
getArray = function (map, name, scale)
|
||||||
local list = map[name]
|
local list = map[name]
|
||||||
local values = {}
|
local values = {}
|
||||||
|
|||||||
@ -97,7 +97,7 @@ function TransformConstraint:applyAbsoluteWorld ()
|
|||||||
local tb = target.b
|
local tb = target.b
|
||||||
local tc = target.c
|
local tc = target.c
|
||||||
local td = target.d
|
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
|
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
|
||||||
local offsetRotation = self.data.offsetRotation * degRadReflect
|
local offsetRotation = self.data.offsetRotation * degRadReflect
|
||||||
local offsetShearY = self.data.offsetShearY * degRadReflect
|
local offsetShearY = self.data.offsetShearY * degRadReflect
|
||||||
@ -184,7 +184,7 @@ function TransformConstraint:applyRelativeWorld ()
|
|||||||
local tb = target.b
|
local tb = target.b
|
||||||
local tc = target.c
|
local tc = target.c
|
||||||
local td = target.d
|
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
|
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
|
||||||
local offsetRotation = self.data.offsetRotation * degRadReflect
|
local offsetRotation = self.data.offsetRotation * degRadReflect
|
||||||
local offsetShearY = self.data.offsetShearY * degRadReflect
|
local offsetShearY = self.data.offsetShearY * degRadReflect
|
||||||
@ -242,7 +242,7 @@ function TransformConstraint:applyRelativeWorld ()
|
|||||||
end
|
end
|
||||||
local b = bone.b
|
local b = bone.b
|
||||||
local d = bone.d
|
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)
|
local s = math_sqrt(b * b + d * d)
|
||||||
bone.b = math_cos(r) * s
|
bone.b = math_cos(r) * s
|
||||||
bone.d = math_sin(r) * s
|
bone.d = math_sin(r) * s
|
||||||
@ -297,7 +297,7 @@ function TransformConstraint:applyAbsoluteLocal ()
|
|||||||
bone.shearY = bone.shearY + r * shearMix
|
bone.shearY = bone.shearY + r * shearMix
|
||||||
end
|
end
|
||||||
|
|
||||||
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,7 @@ function Triangulator:triangulate (verticesArray)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.triangles = {}
|
self.triangles = {}
|
||||||
local triangles = self.triangles;
|
local triangles = self.triangles
|
||||||
|
|
||||||
while vertexCount > 3 do
|
while vertexCount > 3 do
|
||||||
-- Find ear tip.
|
-- Find ear tip.
|
||||||
@ -122,7 +122,7 @@ function Triangulator:triangulate (verticesArray)
|
|||||||
if _next == 0 then
|
if _next == 0 then
|
||||||
repeat
|
repeat
|
||||||
if not isConcave[i] then
|
if not isConcave[i] then
|
||||||
break;
|
break
|
||||||
end
|
end
|
||||||
i = i - 1
|
i = i - 1
|
||||||
until i == 0
|
until i == 0
|
||||||
@ -171,10 +171,10 @@ function Triangulator:decompose(verticesArray, triangles)
|
|||||||
local vertices = verticesArray
|
local vertices = verticesArray
|
||||||
|
|
||||||
self.convexPolygons = {}
|
self.convexPolygons = {}
|
||||||
local convexPolygons = self.convexPolygons;
|
local convexPolygons = self.convexPolygons
|
||||||
|
|
||||||
self.convexPolygonsIndices = {}
|
self.convexPolygonsIndices = {}
|
||||||
local convexPolygonsIndices = self.convexPolygonsIndices;
|
local convexPolygonsIndices = self.convexPolygonsIndices
|
||||||
|
|
||||||
local polygonIndices = {}
|
local polygonIndices = {}
|
||||||
local polygon = {}
|
local polygon = {}
|
||||||
@ -197,12 +197,12 @@ function Triangulator:decompose(verticesArray, triangles)
|
|||||||
local y3 = vertices[t3 + 1]
|
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).
|
-- 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
|
if fanBaseIndex == t1 then
|
||||||
local o = #polygon - 4 + 1;
|
local o = #polygon - 4 + 1
|
||||||
local p = polygon;
|
local p = polygon
|
||||||
local winding1 = self:winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
|
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 winding2 = self:winding(x3, y3, p[1], p[2], p[3], p[4])
|
||||||
if winding1 == lastWinding and winding2 == lastWinding then
|
if winding1 == lastWinding and winding2 == lastWinding then
|
||||||
table_insert(polygon, x3)
|
table_insert(polygon, x3)
|
||||||
table_insert(polygon, y3)
|
table_insert(polygon, y3)
|
||||||
@ -226,8 +226,8 @@ function Triangulator:decompose(verticesArray, triangles)
|
|||||||
table_insert(polygon, y3)
|
table_insert(polygon, y3)
|
||||||
polygonIndices = {}
|
polygonIndices = {}
|
||||||
table_insert(polygonIndices, t1)
|
table_insert(polygonIndices, t1)
|
||||||
table_insert(polygonIndices, t2);
|
table_insert(polygonIndices, t2)
|
||||||
table_insert(polygonIndices, t3);
|
table_insert(polygonIndices, t3)
|
||||||
lastWinding = self:winding(x1, y1, x2, y2, x3, y3)
|
lastWinding = self:winding(x1, y1, x2, y2, x3, y3)
|
||||||
fanBaseIndex = t1
|
fanBaseIndex = t1
|
||||||
end
|
end
|
||||||
@ -266,11 +266,11 @@ function Triangulator:decompose(verticesArray, triangles)
|
|||||||
if ii ~= i then
|
if ii ~= i then
|
||||||
local otherIndices = convexPolygonsIndices[ii]
|
local otherIndices = convexPolygonsIndices[ii]
|
||||||
if (#otherIndices == 3) then
|
if (#otherIndices == 3) then
|
||||||
local otherFirstIndex = otherIndices[1];
|
local otherFirstIndex = otherIndices[1]
|
||||||
local otherSecondIndex = otherIndices[2];
|
local otherSecondIndex = otherIndices[2]
|
||||||
local otherLastIndex = otherIndices[3];
|
local otherLastIndex = otherIndices[3]
|
||||||
|
|
||||||
local otherPoly = convexPolygons[ii];
|
local otherPoly = convexPolygons[ii]
|
||||||
local x3 = otherPoly[#otherPoly - 2 + 1]
|
local x3 = otherPoly[#otherPoly - 2 + 1]
|
||||||
local y3 = otherPoly[#otherPoly - 1 + 1]
|
local y3 = otherPoly[#otherPoly - 1 + 1]
|
||||||
|
|
||||||
@ -308,14 +308,14 @@ function Triangulator:decompose(verticesArray, triangles)
|
|||||||
i = i - 1
|
i = i - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
return convexPolygons;
|
return convexPolygons
|
||||||
end
|
end
|
||||||
|
|
||||||
function Triangulator:isConcave(index, vertexCount, vertices, indices)
|
function Triangulator:isConcave(index, vertexCount, vertices, indices)
|
||||||
local previous = indices[(vertexCount + index - 1) % vertexCount] * 2 + 1;
|
local previous = indices[(vertexCount + index - 1) % vertexCount] * 2 + 1
|
||||||
local current = indices[index] * 2 + 1;
|
local current = indices[index] * 2 + 1
|
||||||
local _next = indices[(index + 1) % vertexCount] * 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]);
|
return not self:positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[_next],vertices[_next + 1])
|
||||||
end
|
end
|
||||||
|
|
||||||
function Triangulator:positiveArea(p1x, p1y, p2x, p2y, p3x, p3y)
|
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
|
if p3x * py - p3y * px + px * p1y - p1x * py >= 0 then
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
return -1;
|
return -1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -84,8 +84,8 @@ function MeshAttachment:updateUVs ()
|
|||||||
local i = 0
|
local i = 0
|
||||||
local n = #uvs
|
local n = #uvs
|
||||||
while i < n do
|
while i < n do
|
||||||
uvs[i + 1] = u + regionUVs[i + 2] * width;
|
uvs[i + 1] = u + regionUVs[i + 2] * width
|
||||||
uvs[i + 2] = v + (1 - regionUVs[i + 1]) * height;
|
uvs[i + 2] = v + (1 - regionUVs[i + 1]) * height
|
||||||
i = i + 2
|
i = i + 2
|
||||||
end
|
end
|
||||||
elseif region.degrees == 180 then
|
elseif region.degrees == 180 then
|
||||||
@ -96,8 +96,8 @@ function MeshAttachment:updateUVs ()
|
|||||||
local i = 0
|
local i = 0
|
||||||
local n = #uvs
|
local n = #uvs
|
||||||
while i < n do
|
while i < n do
|
||||||
uvs[i + 1] = u + (1 - regionUVs[i + 1]) * width;
|
uvs[i + 1] = u + (1 - regionUVs[i + 1]) * width
|
||||||
uvs[i + 2] = v + (1 - regionUVs[i + 2]) * height;
|
uvs[i + 2] = v + (1 - regionUVs[i + 2]) * height
|
||||||
i = i + 2
|
i = i + 2
|
||||||
end
|
end
|
||||||
elseif region.degrees == 270 then
|
elseif region.degrees == 270 then
|
||||||
@ -108,20 +108,20 @@ function MeshAttachment:updateUVs ()
|
|||||||
local i = 0
|
local i = 0
|
||||||
local n = #uvs
|
local n = #uvs
|
||||||
while i < n do
|
while i < n do
|
||||||
uvs[i + 1] = u + (1 - regionUVs[i + 2]) * width;
|
uvs[i + 1] = u + (1 - regionUVs[i + 2]) * width
|
||||||
uvs[i + 2] = v + regionUVs[i + 1] * height;
|
uvs[i + 2] = v + regionUVs[i + 1] * height
|
||||||
i = i + 2
|
i = i + 2
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
u = region.u - region.offsetX / textureWidth;
|
u = region.u - region.offsetX / textureWidth
|
||||||
v = region.v - (region.originalHeight - region.offsetY - region.height) / textureHeight;
|
v = region.v - (region.originalHeight - region.offsetY - region.height) / textureHeight
|
||||||
width = region.originalWidth / textureWidth;
|
width = region.originalWidth / textureWidth
|
||||||
height = region.originalHeight / textureHeight;
|
height = region.originalHeight / textureHeight
|
||||||
local i = 0
|
local i = 0
|
||||||
local n = #uvs
|
local n = #uvs
|
||||||
while i < n do
|
while i < n do
|
||||||
uvs[i + 1] = u + regionUVs[i + 1] * width;
|
uvs[i + 1] = u + regionUVs[i + 1] * width
|
||||||
uvs[i + 2] = v + regionUVs[i + 2] * height;
|
uvs[i + 2] = v + regionUVs[i + 2] * height
|
||||||
i = i + 2
|
i = i + 2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -155,6 +155,7 @@ function RegionAttachment.new (name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function RegionAttachment:updateOffset ()
|
function RegionAttachment:updateOffset ()
|
||||||
|
if not self.region then return end
|
||||||
local regionScaleX = self.width / self.region.originalWidth * self.scaleX
|
local regionScaleX = self.width / self.region.originalWidth * self.scaleX
|
||||||
local regionScaleY = self.height / self.region.originalHeight * self.scaleY
|
local regionScaleY = self.height / self.region.originalHeight * self.scaleY
|
||||||
local localX = -self.width / 2 * self.scaleX + self.region.offsetX * regionScaleX
|
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 AttachmentType = require "spine-lua.attachments.AttachmentType"
|
||||||
local Attachment = require "spine-lua.attachments.Attachment"
|
local Attachment = require "spine-lua.attachments.Attachment"
|
||||||
|
|
||||||
local nextID = 0;
|
local nextID = 0
|
||||||
local SHL_11 = 2048;
|
local SHL_11 = 2048
|
||||||
|
|
||||||
local VertexAttachment = {}
|
local VertexAttachment = {}
|
||||||
VertexAttachment.__index = VertexAttachment
|
VertexAttachment.__index = VertexAttachment
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user