mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
[lua] 4.0 port, runs but LOVE is not rendering.
This commit is contained in:
parent
700d2897a8
commit
137c3f69ed
@ -113,8 +113,8 @@ end
|
||||
function love.load(arg)
|
||||
if arg[#arg] == "-debug" then require("mobdebug").start() end
|
||||
skeletonRenderer = spine.SkeletonRenderer.new(true)
|
||||
table.insert(skeletons, loadSkeleton("mix-and-match-pro", "mix-and-match", "dance", nil, 0.5, 400, 500))
|
||||
table.insert(skeletons, loadSkeleton("spineboy-pro", "spineboy", "walk", nil, 0.5, 400, 500))
|
||||
table.insert(skeletons, loadSkeleton("mix-and-match-pro", "mix-and-match", "dance", nil, 0.5, 400, 500))
|
||||
table.insert(skeletons, loadSkeleton("stretchyman-pro", "stretchyman", "sneak", nil, 0.5, 200, 500))
|
||||
table.insert(skeletons, loadSkeleton("coin-pro", "coin", "animation", nil, 0.5, 400, 300))
|
||||
table.insert(skeletons, loadSkeleton("raptor-pro", "raptor", "walk", nil, 0.3, 400, 500))
|
||||
|
||||
@ -37,7 +37,7 @@ local utils = require "spine-lua.utils"
|
||||
local AttachmentType = require "spine-lua.attachments.AttachmentType"
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local math_floor = math_floor
|
||||
local math_floor = math.floor
|
||||
local math_abs = math.abs
|
||||
local math_signum = utils.signum
|
||||
|
||||
@ -64,14 +64,14 @@ function Animation.new (name, timelines, duration)
|
||||
self.timelineIds = {}
|
||||
for i,timeline in ipairs(self.timelines) do
|
||||
for _,id in ipairs(timeline.propertyIds) do
|
||||
timelineIds[id] = true
|
||||
self.timelineIds[id] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function self:hasTimeline (ids)
|
||||
for _,id in ipairs(ids) do
|
||||
if timelineIds[id] then return true end
|
||||
if self.timelineIds[id] then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
@ -134,11 +134,28 @@ Animation.Property = {
|
||||
}
|
||||
local Property = Animation.Property
|
||||
|
||||
Animation.TimelineType = {
|
||||
rotate = 0,
|
||||
translate = 1, translateX = 2, translateY = 3,
|
||||
scale = 4, scaleX = 5, scaleY = 6,
|
||||
shear = 7, shearX = 8, shearY = 9,
|
||||
rgba = 10, rgb = 11, alpha = 12, rgba2 = 13, rgb2 = 14,
|
||||
attachment = 15,
|
||||
deform = 16,
|
||||
event = 17,
|
||||
drawOrder = 18,
|
||||
ikConstraint = 19,
|
||||
transformConstraint = 20,
|
||||
pathConstraintPosition = 21, pathConstraintSpacing = 22, pathConstraintMix = 23
|
||||
}
|
||||
local TimelineType = Animation.TimelineType
|
||||
|
||||
Animation.Timeline = {}
|
||||
function Animation.Timeline.new (frameCount, propertyIds)
|
||||
function Animation.Timeline.new (timelineType, frameEntries, frameCount, propertyIds)
|
||||
local self = {
|
||||
timelineType = timelineType,
|
||||
propertyIds = propertyIds,
|
||||
frames = utils.newNumberArrayZero((frameCount - 1) * self:getFrameEntries())
|
||||
frames = utils.newNumberArrayZero((frameCount - 1) * frameEntries)
|
||||
}
|
||||
|
||||
function self:getFrameEntries ()
|
||||
@ -158,7 +175,8 @@ end
|
||||
|
||||
local function search1 (frames, time)
|
||||
local n = zlen(frames)
|
||||
while i <= n do
|
||||
local i = 1
|
||||
while i < n do
|
||||
if frames[i] > time then return i - 1 end
|
||||
i = i + 1
|
||||
end
|
||||
@ -169,7 +187,7 @@ Animation.Timeline.search1 = search1
|
||||
local function search (frames, time, step)
|
||||
local n = zlen(frames)
|
||||
local i = step
|
||||
while i <= n do
|
||||
while i < n do
|
||||
if frames[i] > time then return i - step end
|
||||
i = i + step
|
||||
end
|
||||
@ -182,14 +200,15 @@ local BEZIER = 2
|
||||
local BEZIER_SIZE = 18
|
||||
|
||||
Animation.CurveTimeline = {}
|
||||
function Animation.CurveTimeline.new (frameCount, bezierCount, propertyIds)
|
||||
function Animation.CurveTimeline.new (timelineType, frameEntries, frameCount, bezierCount, propertyIds)
|
||||
local LINEAR = 0
|
||||
local STEPPED = 1
|
||||
local BEZIER = 2
|
||||
local BEZIER_SIZE = 10 * 2 - 1
|
||||
|
||||
local self = Animation.Timeline.new(frameCount, propertyIds)
|
||||
local self = Animation.Timeline.new(timelineType, frameEntries, frameCount, propertyIds)
|
||||
self.curves = utils.newNumberArrayZero(frameCount + bezierCount * BEZIER_SIZE)
|
||||
self.curves[frameCount - 1] = STEPPED
|
||||
|
||||
function self:getFrameCount ()
|
||||
return math_floor(zlen(self.curves) / BEZIER_SIZE) + 1
|
||||
@ -261,11 +280,11 @@ function Animation.CurveTimeline.new (frameCount, bezierCount, propertyIds)
|
||||
end
|
||||
|
||||
Animation.CurveTimeline1 = {}
|
||||
function Animation.CurveTimeline1.new (frameCount, bezierCount, propertyId)
|
||||
function Animation.CurveTimeline1.new (timelineType, frameCount, bezierCount, propertyId)
|
||||
local ENTRIES = 2
|
||||
local VALUE = 1
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { propertyId })
|
||||
local self = Animation.CurveTimeline.new(timelineType, ENTRIES, frameCount, bezierCount, { propertyId })
|
||||
|
||||
function self:getFrameEntries ()
|
||||
return ENTRIES
|
||||
@ -303,12 +322,12 @@ function Animation.CurveTimeline1.new (frameCount, bezierCount, propertyId)
|
||||
end
|
||||
|
||||
Animation.CurveTimeline2 = {}
|
||||
function Animation.CurveTimeline2.new (frameCount, bezierCount, propertyId1, propertyId2)
|
||||
function Animation.CurveTimeline2.new (timelineType, frameCount, bezierCount, propertyId1, propertyId2)
|
||||
local ENTRIES = 3
|
||||
local VALUE1 = 1
|
||||
local VALUE2 = 2
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { propertyId1, propertyId2 })
|
||||
local self = Animation.CurveTimeline.new(timelineType, ENTRIES, frameCount, bezierCount, { propertyId1, propertyId2 })
|
||||
|
||||
function self:getFrameEntries ()
|
||||
return ENTRIES
|
||||
@ -326,7 +345,7 @@ end
|
||||
|
||||
Animation.RotateTimeline = {}
|
||||
function Animation.RotateTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.rotate.."|"..boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.rotate, frameCount, bezierCount, Property.rotate.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -358,7 +377,11 @@ end
|
||||
|
||||
Animation.TranslateTimeline = {}
|
||||
function Animation.TranslateTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline2.new(frameCount, bezierCount,
|
||||
local ENTRIES = 3
|
||||
local VALUE1 = 1
|
||||
local VALUE2 = 2
|
||||
|
||||
local self = Animation.CurveTimeline2.new(TimelineType.translate, frameCount, bezierCount,
|
||||
Property.x.."|"..boneIndex,
|
||||
Property.y.."|"..boneIndex
|
||||
)
|
||||
@ -382,7 +405,7 @@ function Animation.TranslateTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
|
||||
local x = 0
|
||||
local y = 0
|
||||
local frame = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / ENTRIES)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -416,7 +439,7 @@ end
|
||||
|
||||
Animation.TranslateXTimeline = {}
|
||||
function Animation.TranslateXTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.x.."|"..boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.translateX, frameCount, bezierCount, Property.x.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -448,7 +471,7 @@ end
|
||||
|
||||
Animation.TranslateYTimeline = {}
|
||||
function Animation.TranslateYTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.x.."|"..boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.translateY, frameCount, bezierCount, Property.x.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -480,7 +503,11 @@ end
|
||||
|
||||
Animation.ScaleTimeline = {}
|
||||
function Animation.ScaleTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline2.new(frameCount, bezierCount,
|
||||
local ENTRIES = 3
|
||||
local VALUE1 = 1
|
||||
local VALUE2 = 2
|
||||
|
||||
local self = Animation.CurveTimeline2.new(TimelineType.scale, frameCount, bezierCount,
|
||||
Property.scaleX.."|"..boneIndex,
|
||||
Property.scaleY.."|"..boneIndex
|
||||
)
|
||||
@ -504,7 +531,7 @@ function Animation.ScaleTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
|
||||
local x = 0
|
||||
local y = 0
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / ENTRIES)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -577,7 +604,7 @@ end
|
||||
|
||||
Animation.ScaleXTimeline = {}
|
||||
function Animation.ScaleXTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.scaleX.."|"..boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.scaleX, frameCount, bezierCount, Property.scaleX.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -634,7 +661,7 @@ end
|
||||
|
||||
Animation.ScaleYTimeline = {}
|
||||
function Animation.ScaleYTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.scaleY.."|"..boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.scaleY, frameCount, bezierCount, Property.scaleY.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -690,8 +717,12 @@ function Animation.ScaleYTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
end
|
||||
|
||||
Animation.ShearTimeline = {}
|
||||
function Animation.ShearTimeline.new (frameCount)
|
||||
local self = Animation.CurveTimeline2.new(frameCount, bezierCount,
|
||||
function Animation.ShearTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local ENTRIES = 3
|
||||
local VALUE1 = 1
|
||||
local VALUE2 = 2
|
||||
|
||||
local self = Animation.CurveTimeline2.new(TimelineType.shear, frameCount, bezierCount,
|
||||
Property.shearX.."|"..boneIndex,
|
||||
Property.shearY.."|"..boneIndex
|
||||
)
|
||||
@ -715,7 +746,7 @@ function Animation.ShearTimeline.new (frameCount)
|
||||
|
||||
local x = 0
|
||||
local y = 0
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / ENTRIES)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -748,8 +779,8 @@ function Animation.ShearTimeline.new (frameCount)
|
||||
end
|
||||
|
||||
Animation.ShearXTimeline = {}
|
||||
function Animation.ShearXTimeline.new (frameCount)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.shearX.."|"..boneIndex)
|
||||
function Animation.ShearXTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.shearX, frameCount, bezierCount, Property.shearX.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -780,8 +811,8 @@ function Animation.ShearXTimeline.new (frameCount)
|
||||
end
|
||||
|
||||
Animation.ShearYTimeline = {}
|
||||
function Animation.ShearYTimeline.new (frameCount)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.shearY.."|"..boneIndex)
|
||||
function Animation.ShearYTimeline.new (frameCount, bezierCount, boneIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.shearY, frameCount, bezierCount, Property.shearY.."|"..boneIndex)
|
||||
self.boneIndex = boneIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -819,7 +850,7 @@ function Animation.RGBATimeline.new (frameCount, bezierCount, slotIndex)
|
||||
local B = 3
|
||||
local A = 4
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, {
|
||||
local self = Animation.CurveTimeline.new(TimelineType.rgba, ENTRIES, frameCount, bezierCount, {
|
||||
Property.rgb.."|"..slotIndex,
|
||||
Property.alpha.."|"..slotIndex
|
||||
})
|
||||
@ -856,7 +887,7 @@ function Animation.RGBATimeline.new (frameCount, bezierCount, slotIndex)
|
||||
end
|
||||
|
||||
local r, g, b, a
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[i / ENTRIES]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -899,7 +930,7 @@ function Animation.RGBTimeline.new (frameCount, bezierCount, slotIndex)
|
||||
local G = 2
|
||||
local B = 3
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { Property.rgb.."|"..slotIndex })
|
||||
local self = Animation.CurveTimeline.new(TimelineType.rgb, ENTRIES, frameCount, bezierCount, { Property.rgb.."|"..slotIndex })
|
||||
self.slotIndex = slotIndex
|
||||
|
||||
function self:getFrameEntries ()
|
||||
@ -935,7 +966,7 @@ function Animation.RGBTimeline.new (frameCount, bezierCount, slotIndex)
|
||||
end
|
||||
|
||||
local r, g, b
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[i / ENTRIES]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -978,7 +1009,7 @@ end
|
||||
|
||||
Animation.AlphaTimeline = {}
|
||||
function Animation.AlphaTimeline.new (frameCount, bezierCount, slotIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.alpha.."|"..slotIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.alpha, frameCount, bezierCount, Property.alpha.."|"..slotIndex)
|
||||
self.slotIndex = slotIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -1020,7 +1051,7 @@ function Animation.RGBA2Timeline.new (frameCount, bezierCount, slotIndex)
|
||||
local G2 = 6
|
||||
local B2 = 7
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, {
|
||||
local self = Animation.CurveTimeline.new(TimelineType.rgba2, ENTRIES, frameCount, bezierCount, {
|
||||
Property.rgb.."|"..slotIndex,
|
||||
Property.alpha.."|"..slotIndex,
|
||||
Property.rgb2.."|"..slotIndex
|
||||
@ -1069,7 +1100,7 @@ function Animation.RGBA2Timeline.new (frameCount, bezierCount, slotIndex)
|
||||
end
|
||||
|
||||
local r, g, b, a, r2, g2, b2
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / ENTRIES)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -1139,7 +1170,7 @@ function Animation.RGB2Timeline.new (frameCount, bezierCount, slotIndex)
|
||||
local G2 = 5
|
||||
local B2 = 6
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, {
|
||||
local self = Animation.CurveTimeline.new(TimelineType.rgb2, ENTRIES, frameCount, bezierCount, {
|
||||
Property.rgb.."|"..slotIndex,
|
||||
Property.rgb2.."|"..slotIndex
|
||||
})
|
||||
@ -1189,7 +1220,7 @@ function Animation.RGB2Timeline.new (frameCount, bezierCount, slotIndex)
|
||||
end
|
||||
|
||||
local r, g, b, r2, g2, b2
|
||||
local i = search2(frames, time, ENTRIES)
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / ENTRIES)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i]
|
||||
@ -1254,7 +1285,7 @@ end
|
||||
|
||||
Animation.AttachmentTimeline = {}
|
||||
function Animation.AttachmentTimeline.new (frameCount, bezierCount, slotIndex)
|
||||
local self = Animation.Timeline.new(frameCount, { Property.attachment + "|" + slotIndex })
|
||||
local self = Animation.Timeline.new(TimelineType.attachment, 1, frameCount, { Property.attachment.."|"..slotIndex })
|
||||
self.slotIndex = slotIndex
|
||||
self.attachmentNames = {}
|
||||
|
||||
@ -1311,7 +1342,7 @@ end
|
||||
|
||||
Animation.DeformTimeline = {}
|
||||
function Animation.DeformTimeline.new (frameCount, bezierCount, slotIndex, attachment)
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { Property.deform + "|" + slotIndex + "|" + attachment.id })
|
||||
local self = Animation.CurveTimeline.new(TimelineType.deform, 1, frameCount, bezierCount, { Property.deform.."|"..slotIndex.."|"..attachment.id })
|
||||
self.slotIndex = slotIndex
|
||||
self.attachment = attachment
|
||||
self.vertices = {}
|
||||
@ -1353,7 +1384,7 @@ function Animation.DeformTimeline.new (frameCount, bezierCount, slotIndex, attac
|
||||
end
|
||||
end
|
||||
|
||||
function getCurvePercent (time, frame)
|
||||
function self:getCurvePercent (time, frame)
|
||||
local curves = self.curves
|
||||
local i = curves[frame]
|
||||
if i == LINEAR then
|
||||
@ -1387,7 +1418,7 @@ function Animation.DeformTimeline.new (frameCount, bezierCount, slotIndex, attac
|
||||
if not slot.bone.active then return end
|
||||
|
||||
local vertexAttachment = slot.attachment
|
||||
if not vertexAttachment or not vertexAttachment.vertexAttachment or vertexAttachment.deformAttachment ~= self.attachment then return end
|
||||
if not vertexAttachment or not vertexAttachment.isVertexAttachment or vertexAttachment.deformAttachment ~= self.attachment then return end
|
||||
|
||||
local frames = self.frames
|
||||
local deform = slot.deform
|
||||
@ -1604,7 +1635,7 @@ end
|
||||
Animation.EventTimeline = {}
|
||||
local eventPropertyIds = { Property.event }
|
||||
function Animation.EventTimeline.new (frameCount)
|
||||
local self = Animation.Timeline.new(frameCount, eventPropertyIds)
|
||||
local self = Animation.Timeline.new(TimelineType.event, 1, frameCount, eventPropertyIds)
|
||||
self.events = {}
|
||||
|
||||
function self:getFrameCount ()
|
||||
@ -1635,7 +1666,7 @@ function Animation.EventTimeline.new (frameCount)
|
||||
if lastTime < frames[0] then
|
||||
i = 0
|
||||
else
|
||||
i = binarySearch1(frames, lastTime)
|
||||
i = search1(frames, lastTime) + 1
|
||||
local i = frames[i]
|
||||
while i > 0 do -- Fire multiple events with the same frame.
|
||||
if frames[i - 1] ~= i then break end
|
||||
@ -1654,7 +1685,7 @@ end
|
||||
Animation.DrawOrderTimeline = {}
|
||||
local drawOrderPropertyIds = { Property.drawOrder }
|
||||
function Animation.DrawOrderTimeline.new (frameCount)
|
||||
local self = Animation.Timeline.new(frameCount, drawOrderPropertyIds)
|
||||
local self = Animation.Timeline.new(TimelineType.drawOrder, 1, frameCount, drawOrderPropertyIds)
|
||||
self.drawOrders = {}
|
||||
|
||||
function self:getFrameCount ()
|
||||
@ -1667,6 +1698,9 @@ function Animation.DrawOrderTimeline.new (frameCount)
|
||||
end
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
local drawOrder = skeleton.drawOrder
|
||||
local slots = skeleton.slots
|
||||
|
||||
if direction == MixDirection.mixOut then
|
||||
if blend == MixBlend.setup then
|
||||
for i,slot in ipairs(slots) do
|
||||
@ -1691,8 +1725,6 @@ function Animation.DrawOrderTimeline.new (frameCount)
|
||||
drawOrder[i] = slots[i]
|
||||
end
|
||||
else
|
||||
local drawOrder = skeleton.drawOrder
|
||||
local slots = skeleton.slots
|
||||
for i,setupIndex in ipairs(drawOrderToSetupIndex) do
|
||||
drawOrder[i] = skeleton.slots[setupIndex]
|
||||
end
|
||||
@ -1711,7 +1743,7 @@ function Animation.IkConstraintTimeline.new (frameCount, bezierCount, ikConstrai
|
||||
local COMPRESS = 4
|
||||
local STRETCH = 5
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { Property.ikConstraint + "|" + ikConstraintIndex })
|
||||
local self = Animation.CurveTimeline.new(TimelineType.ikConstraint, ENTRIES, frameCount, bezierCount, { Property.ikConstraint.."|"..ikConstraintIndex })
|
||||
self.ikConstraintIndex = ikConstraintIndex
|
||||
|
||||
function self:getFrameEntries ()
|
||||
@ -1804,7 +1836,7 @@ function Animation.IkConstraintTimeline.new (frameCount, bezierCount, ikConstrai
|
||||
end
|
||||
|
||||
Animation.TransformConstraintTimeline = {}
|
||||
function Animation.TransformConstraintTimeline.new (frameCount, transformConstraintIndex)
|
||||
function Animation.TransformConstraintTimeline.new (frameCount, bezierCount, transformConstraintIndex)
|
||||
local ENTRIES = 7
|
||||
local ROTATE = 1
|
||||
local X = 2
|
||||
@ -1813,7 +1845,7 @@ function Animation.TransformConstraintTimeline.new (frameCount, transformConstra
|
||||
local SCALEY = 5
|
||||
local SHEARY = 6
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, { Property.transformConstraint + "|" + transformConstraintIndex })
|
||||
local self = Animation.CurveTimeline.new(TimelineType.transformConstraint, ENTRIES, frameCount, bezierCount, { Property.transformConstraint.."|"..transformConstraintIndex })
|
||||
self.transformConstraintIndex = transformConstraintIndex
|
||||
|
||||
function self:getFrameEntries ()
|
||||
@ -1918,7 +1950,7 @@ end
|
||||
|
||||
Animation.PathConstraintPositionTimeline = {}
|
||||
function Animation.PathConstraintPositionTimeline.new (frameCount, bezierCount, pathConstraintIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.pathConstraintPosition.."|"..pathConstraintIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.pathConstraintPosition, frameCount, bezierCount, Property.pathConstraintPosition.."|"..pathConstraintIndex)
|
||||
self.pathConstraintIndex = pathConstraintIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -1948,7 +1980,7 @@ end
|
||||
|
||||
Animation.PathConstraintSpacingTimeline = {}
|
||||
function Animation.PathConstraintSpacingTimeline.new (frameCount, bezierCount, pathConstraintIndex)
|
||||
local self = Animation.CurveTimeline1.new(frameCount, bezierCount, Property.pathConstraintSpacing.."|"..pathConstraintIndex)
|
||||
local self = Animation.CurveTimeline1.new(TimelineType.pathConstraintSpacing, frameCount, bezierCount, Property.pathConstraintSpacing.."|"..pathConstraintIndex)
|
||||
self.pathConstraintIndex = pathConstraintIndex
|
||||
|
||||
function self:apply (skeleton, lastTime, time, events, alpha, blend, direction)
|
||||
@ -1983,7 +2015,7 @@ function Animation.PathConstraintMixTimeline.new (frameCount, bezierCount, pathC
|
||||
local X = 2
|
||||
local Y = 3
|
||||
|
||||
local self = Animation.CurveTimeline.new(frameCount, bezierCount, Property.pathConstraintMix.."|"..pathConstraintIndex)
|
||||
local self = Animation.CurveTimeline.new(TimelineType.pathConstraintMix, ENTRIES, frameCount, bezierCount, Property.pathConstraintMix.."|"..pathConstraintIndex)
|
||||
self.pathConstraintIndex = pathConstraintIndex
|
||||
|
||||
function self:getFrameEntries ()
|
||||
@ -2006,13 +2038,13 @@ function Animation.PathConstraintMixTimeline.new (frameCount, bezierCount, pathC
|
||||
local frames = self.frames
|
||||
if time < frames[0] then
|
||||
if blend == MixBlend.setup then
|
||||
constraint.mixRotate = constraint.data.mixRotate;
|
||||
constraint.mixX = constraint.data.mixX;
|
||||
constraint.mixY = constraint.data.mixY;
|
||||
constraint.mixRotate = constraint.data.mixRotate
|
||||
constraint.mixX = constraint.data.mixX
|
||||
constraint.mixY = constraint.data.mixY
|
||||
elseif blend == MixBlend.first then
|
||||
constraint.mixRotate = constraint.mixRotate + (constraint.data.mixRotate - constraint.mixRotate) * alpha;
|
||||
constraint.mixX = constraint.mixX + (constraint.data.mixX - constraint.mixX) * alpha;
|
||||
constraint.mixY = constraint.mixY + (constraint.data.mixY - constraint.mixY) * alpha;
|
||||
constraint.mixRotate = constraint.mixRotate + (constraint.data.mixRotate - constraint.mixRotate) * alpha
|
||||
constraint.mixX = constraint.mixX + (constraint.data.mixX - constraint.mixX) * alpha
|
||||
constraint.mixY = constraint.mixY + (constraint.data.mixY - constraint.mixY) * alpha
|
||||
end
|
||||
return
|
||||
end
|
||||
@ -2020,36 +2052,36 @@ function Animation.PathConstraintMixTimeline.new (frameCount, bezierCount, pathC
|
||||
local rotate
|
||||
local x
|
||||
local y
|
||||
local i = search(frames, time, ENTRIES);
|
||||
local curveType = self.curves[math_floor(i / 4)];
|
||||
local i = search(frames, time, ENTRIES)
|
||||
local curveType = self.curves[math_floor(i / 4)]
|
||||
if curveType == LINEAR then
|
||||
local before = frames[i];
|
||||
rotate = frames[i + ROTATE];
|
||||
x = frames[i + X];
|
||||
y = frames[i + Y];
|
||||
local t = (time - before) / (frames[i + ENTRIES] - before);
|
||||
rotate = rotate + (frames[i + ENTRIES + ROTATE] - rotate) * t;
|
||||
x = x + (frames[i + ENTRIES + X] - x) * t;
|
||||
y = y + (frames[i + ENTRIES + Y] - y) * t;
|
||||
local before = frames[i]
|
||||
rotate = frames[i + ROTATE]
|
||||
x = frames[i + X]
|
||||
y = frames[i + Y]
|
||||
local t = (time - before) / (frames[i + ENTRIES] - before)
|
||||
rotate = rotate + (frames[i + ENTRIES + ROTATE] - rotate) * t
|
||||
x = x + (frames[i + ENTRIES + X] - x) * t
|
||||
y = y + (frames[i + ENTRIES + Y] - y) * t
|
||||
elseif curveType == STEPPED then
|
||||
rotate = frames[i + ROTATE];
|
||||
x = frames[i + X];
|
||||
y = frames[i + Y];
|
||||
rotate = frames[i + ROTATE]
|
||||
x = frames[i + X]
|
||||
y = frames[i + Y]
|
||||
else
|
||||
rotate = this.getBezierValue(time, i, ROTATE, curveType - BEZIER);
|
||||
x = this.getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
|
||||
y = this.getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
rotate = this.getBezierValue(time, i, ROTATE, curveType - BEZIER)
|
||||
x = this.getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER)
|
||||
y = this.getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER)
|
||||
end
|
||||
|
||||
if blend == MixBlend.setup then
|
||||
local data = constraint.data;
|
||||
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
||||
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
||||
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
||||
local data = constraint.data
|
||||
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha
|
||||
constraint.mixX = data.mixX + (x - data.mixX) * alpha
|
||||
constraint.mixY = data.mixY + (y - data.mixY) * alpha
|
||||
else
|
||||
constraint.mixRotate = constraint.mixRotate + (rotate - constraint.mixRotate) * alpha;
|
||||
constraint.mixX = constraint.mixX + (x - constraint.mixX) * alpha;
|
||||
constraint.mixY = constraint.mixY + (y - constraint.mixY) * alpha;
|
||||
constraint.mixRotate = constraint.mixRotate + (rotate - constraint.mixRotate) * alpha
|
||||
constraint.mixX = constraint.mixX + (x - constraint.mixX) * alpha
|
||||
constraint.mixY = constraint.mixY + (y - constraint.mixY) * alpha
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -198,12 +198,22 @@ function TrackEntry:getAnimationTime ()
|
||||
return math_min(self.trackTime + self.animationStart, self.animationEnd)
|
||||
end
|
||||
|
||||
function TrackEntry:getTrackComplete ()
|
||||
local duration = self.animationEnd - self.animationStart
|
||||
if duration ~= 0 then
|
||||
if self.loop then return duration * (1 + math_floor(self.trackTime / duration)) end -- Completion of next loop.
|
||||
if self.trackTime < duration then return duration end -- Before duration.
|
||||
end
|
||||
return self.trackTime -- Next update.
|
||||
end
|
||||
|
||||
function TrackEntry:resetRotationDirections ()
|
||||
self.timelinesRotation = {}
|
||||
end
|
||||
|
||||
local AnimationState = {}
|
||||
AnimationState.__index = AnimationState
|
||||
AnimationState.TrackEntry = TrackEntry
|
||||
|
||||
function AnimationState.new (data)
|
||||
if not data then error("data cannot be nil", 2) end
|
||||
@ -225,8 +235,6 @@ function AnimationState.new (data)
|
||||
return self
|
||||
end
|
||||
|
||||
AnimationState.TrackEntry = TrackEntry
|
||||
|
||||
function AnimationState:update (delta)
|
||||
delta = delta * self.timeScale
|
||||
local tracks = self.tracks
|
||||
@ -359,31 +367,35 @@ function AnimationState:apply (skeleton)
|
||||
-- Apply current entry.
|
||||
local animationLast = current.animationLast
|
||||
local animationTime = current:getAnimationTime()
|
||||
local applyTime = animationTime
|
||||
local applyEvents = self.events
|
||||
if current.reverse then
|
||||
applyTime = current.animation.duration - applyTime
|
||||
applyEvents = nil
|
||||
end
|
||||
local timelines = current.animation.timelines
|
||||
if (i == 0 and mix == 1) or blend == MixBlend.add then
|
||||
for i,timeline in ipairs(timelines) do
|
||||
if timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true)
|
||||
self:applyAttachmentTimeline(timeline, skeleton, applyTime, blend, true)
|
||||
else
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, mix, blend, MixDirection.mixIn)
|
||||
timeline:apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection.mixIn)
|
||||
end
|
||||
end
|
||||
else
|
||||
local timelineMode = current.timelineMode
|
||||
local firstFrame = #current.timelinesRotation == 0
|
||||
local timelinesRotation = current.timelinesRotation
|
||||
local firstFrame = #current.timelinesRotation ~= #timelines * 2
|
||||
|
||||
for ii,timeline in ipairs(timelines) do
|
||||
local timelineBlend = MixBlend.setup
|
||||
if timelineMode[ii] == SUBSEQUENT then timelineBlend = blend end
|
||||
|
||||
if timeline.type == Animation.TimelineType.rotate then
|
||||
self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii * 2,
|
||||
firstFrame)
|
||||
self:applyRotateTimeline(timeline, skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii * 2, firstFrame)
|
||||
elseif timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, true)
|
||||
self:applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, true)
|
||||
else
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, mix, timelineBlend, MixDirection.mixIn)
|
||||
timeline:apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, MixDirection.mixIn)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -401,7 +413,7 @@ function AnimationState:apply (skeleton)
|
||||
-- the time is before the first key).
|
||||
local setupState = self.unkeyedState + SETUP
|
||||
local slots = skeleton.slots
|
||||
for _, slot in ipairs(slots) do
|
||||
for _,slot in ipairs(slots) do
|
||||
if slot.attachmentState == setupState then
|
||||
local attachmentName = slot.data.attachmentName
|
||||
if attachmentName == nil then
|
||||
@ -432,25 +444,31 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
if blend ~= MixBlend.first then blend = from.mixBlend end
|
||||
end
|
||||
|
||||
local events = nil
|
||||
if mix < from.eventThreshold then events = self.events end
|
||||
|
||||
local attachments = mix < from.attachmentThreshold
|
||||
local drawOrder = mix < from.drawOrderThreshold
|
||||
local animationLast = from.animationLast
|
||||
local animationTime = from:getAnimationTime()
|
||||
local timelines = from.animation.timelines
|
||||
local alphaHold = from.alpha * to.interruptAlpha
|
||||
local alphaMix = alphaHold * (1 - mix)
|
||||
local animationLast = from.animationLast
|
||||
local animationTime = from:getAnimationTime()
|
||||
local applyTime = animationTime
|
||||
local events = nil
|
||||
if from.reverse then
|
||||
applyTime = from.animation.duration - applyTime
|
||||
elseif mix < from.eventThreshold then
|
||||
events = self.events
|
||||
end
|
||||
|
||||
if blend == MixBlend.add then
|
||||
for i,timeline in ipairs(timelines) do
|
||||
timeline:apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.mixOut)
|
||||
timeline:apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.mixOut)
|
||||
end
|
||||
else
|
||||
local timelineMode = from.timelineMode
|
||||
local timelineHoldMix = from.timelineHoldMix
|
||||
|
||||
local firstFrame = #from.timelinesRotation == 0
|
||||
local firstFrame = #from.timelinesRotation ~= #timelines
|
||||
local timelinesRotation = from.timelinesRotation
|
||||
|
||||
from.totalAlpha = 0
|
||||
@ -473,7 +491,7 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
elseif timelineMode[i] == HOLD_FIRST then
|
||||
timelineBlend = MixBlend.setup
|
||||
alpha = alphaHold
|
||||
else
|
||||
else -- HOLD_MIX
|
||||
timelineBlend = MixBlend.setup
|
||||
local holdMix = timelineHoldMix[i]
|
||||
alpha = alphaHold * math_max(0, 1 - holdMix.mixtime / holdMix.mixDuration)
|
||||
@ -482,14 +500,14 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
if not skipSubsequent then
|
||||
from.totalAlpha = from.totalAlpha + alpha
|
||||
if timeline.type == Animation.TimelineType.rotate then
|
||||
self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
|
||||
self:applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
|
||||
elseif timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments)
|
||||
self:applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments)
|
||||
else
|
||||
if drawOrder and timeline.type == Animation.TimelineType.drawOrder and timelineBlend == MixBlend.setup then
|
||||
direction = MixDirection.mixIn
|
||||
end
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, alpha, timelineBlend, direction)
|
||||
timeline:apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -509,19 +527,12 @@ function AnimationState:applyAttachmentTimeline(timeline, skeleton, time, blend,
|
||||
local slot = skeleton.slots[timeline.slotIndex]
|
||||
if slot.bone.active == false then return end
|
||||
|
||||
local frames = timeline.frames
|
||||
if time < frames[0] then -- Time is before first frame.
|
||||
if time < timeline.frames[0] then -- Time is before first frame.
|
||||
if blend == MixBlend.setup or blend == MixBlend.first then
|
||||
self:setAttachment(skeleton, slot, slot.data.attachmentName, attachments)
|
||||
end
|
||||
else
|
||||
local frameIndex = 0
|
||||
if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
|
||||
frameIndex = zlen(frames) - 1
|
||||
else
|
||||
frameIndex = Animation.binarySearch(frames, time, 1) - 1
|
||||
end
|
||||
self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
|
||||
self:setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments)
|
||||
end
|
||||
|
||||
-- If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.
|
||||
@ -548,10 +559,9 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, bl
|
||||
return
|
||||
end
|
||||
|
||||
local rotateTimeline = timeline
|
||||
local frames = rotateTimeline.frames
|
||||
local bone = skeleton.bones[rotateTimeline.boneIndex]
|
||||
local bone = skeleton.bones[timeline.boneIndex]
|
||||
if not bone.active then return end
|
||||
local frames = timeline.frames
|
||||
local r1 = 0
|
||||
local r2 = 0
|
||||
if time < frames[0] then
|
||||
@ -570,21 +580,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, bl
|
||||
else
|
||||
r1 = bone.rotation
|
||||
end
|
||||
if time >= frames[zlen(frames) - Animation.RotateTimeline.ENTRIES] then -- Time is after last frame.
|
||||
r2 = bone.data.rotation + frames[zlen(frames) + Animation.RotateTimeline.PREV_ROTATION]
|
||||
else
|
||||
-- Interpolate between the previous frame and the current frame.
|
||||
local frame = Animation.binarySearch(frames, time, Animation.RotateTimeline.ENTRIES)
|
||||
local prevRotation = frames[frame + Animation.RotateTimeline.PREV_ROTATION]
|
||||
local frameTime = frames[frame]
|
||||
local percent = rotateTimeline:getCurvePercent(math_floor(frame / 2) - 1,
|
||||
1 - (time - frameTime) / (frames[frame + Animation.RotateTimeline.PREV_TIME] - frameTime))
|
||||
|
||||
r2 = frames[frame + Animation.RotateTimeline.ROTATION] - prevRotation
|
||||
r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
|
||||
r2 = prevRotation + r2 * percent + bone.data.rotation
|
||||
r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
|
||||
end
|
||||
r2 = bone.data.rotation + timeline:getCurveValue(time)
|
||||
end
|
||||
|
||||
-- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
||||
@ -616,8 +612,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, bl
|
||||
timelinesRotation[i] = total
|
||||
end
|
||||
timelinesRotation[i + 1] = diff
|
||||
r1 = r1 + total * alpha
|
||||
bone.rotation = r1 - (16384 - math_floor(16384.499999999996 - r1 / 360)) * 360
|
||||
bone.rotation = r1 + total * alpha
|
||||
end
|
||||
|
||||
function AnimationState:queueEvents (entry, animationTime)
|
||||
@ -654,7 +649,7 @@ function AnimationState:queueEvents (entry, animationTime)
|
||||
-- Queue events after complete.
|
||||
while i <= n do
|
||||
local event = events[i]
|
||||
if not (event.time < animationStart) then --// Discard events outside animation start/end.
|
||||
if event.time >= animationStart then -- Discard events outside animation start/end.
|
||||
queue:event(entry, event)
|
||||
end
|
||||
i = i + 1
|
||||
@ -701,14 +696,17 @@ function AnimationState:clearTrack (trackIndex)
|
||||
queue:drain()
|
||||
end
|
||||
|
||||
function AnimationState:clearNext (entry)
|
||||
self:disposeNext(entry.next)
|
||||
end
|
||||
|
||||
function AnimationState:setCurrent (index, current, interrupt)
|
||||
local from = self:expandToIndex(index)
|
||||
local tracks = self.tracks
|
||||
local queue = self.queue
|
||||
tracks[index] = current
|
||||
self.tracks[index] = current
|
||||
current.previous = nil
|
||||
|
||||
if from then
|
||||
if interrupt then queue:interrupt(from) end
|
||||
if interrupt then self.queue:interrupt(from) end
|
||||
current.mixingFrom = from
|
||||
from.mixingTo = current
|
||||
current.mixTime = 0
|
||||
@ -720,7 +718,7 @@ function AnimationState:setCurrent (index, current, interrupt)
|
||||
from.timelinesRotation = {}
|
||||
end
|
||||
|
||||
queue:start(current)
|
||||
self.queue:start(current)
|
||||
end
|
||||
|
||||
function AnimationState:setAnimationByName (trackIndex, animationName, loop)
|
||||
@ -779,19 +777,8 @@ function AnimationState:addAnimation (trackIndex, animation, loop, delay)
|
||||
queue:drain()
|
||||
else
|
||||
last.next = entry
|
||||
if delay <= 0 then
|
||||
local duration = last.animationEnd - last.animationStart
|
||||
if duration ~= 0 then
|
||||
if last.loop then
|
||||
delay = delay + duration * (1 + math_floor(last.trackTime / duration))
|
||||
else
|
||||
delay = delay + math_max(duration, last.trackTime)
|
||||
end
|
||||
delay = delay - data:getMix(last.animation, animation)
|
||||
else
|
||||
delay = last.trackTime
|
||||
end
|
||||
end
|
||||
entry.previous = last
|
||||
if delay <= 0 then delay = delay + last:getTrackComplete() - entry.mixDuration end
|
||||
end
|
||||
|
||||
entry.delay = delay
|
||||
@ -806,10 +793,14 @@ function AnimationState:setEmptyAnimation (trackIndex, mixDuration)
|
||||
end
|
||||
|
||||
function AnimationState:addEmptyAnimation (trackIndex, mixDuration, delay)
|
||||
if delay <= 0 then delay = delay - mixDuration end
|
||||
local entry = self:addAnimation(trackIndex, EMPTY_ANIMATION, false, delay)
|
||||
local addDelay = 1
|
||||
if delay > 0 then addDelay = delay end
|
||||
local entry = self:addAnimation(trackIndex, EMPTY_ANIMATION, false, addDelay)
|
||||
entry.mixDuration = mixDuration
|
||||
entry.trackEnd = mixDuration
|
||||
if delay <= 0 and entry.previous then
|
||||
entry.delay = entry.previous:getTrackComplete() - entry.mixDuration + delay
|
||||
end
|
||||
return entry
|
||||
end
|
||||
|
||||
@ -895,28 +886,19 @@ function AnimationState:_animationsChanged ()
|
||||
self.animationsChanged = false
|
||||
|
||||
self.propertyIDs = {}
|
||||
|
||||
local highestIndex = -1
|
||||
local tracks = self.tracks
|
||||
local numTracks = getNumTracks(tracks)
|
||||
local i = 0
|
||||
while i <= numTracks do
|
||||
entry = tracks[i]
|
||||
local n = zlen(tracks)
|
||||
while i < n do
|
||||
local entry = tracks[i]
|
||||
if entry then
|
||||
if i > highestIndex then highestIndex = i end
|
||||
|
||||
if entry then
|
||||
while entry.mixingFrom do
|
||||
entry = entry.mixingFrom
|
||||
end
|
||||
|
||||
repeat
|
||||
if entry.mixingTo == nil or entry.mixBlend ~= MixBlend.add then
|
||||
self:computeHold(entry)
|
||||
end
|
||||
entry = entry.mixingTo
|
||||
until (entry == nil)
|
||||
while entry.mixingFrom do
|
||||
entry = entry.mixingFrom
|
||||
end
|
||||
repeat
|
||||
if not entry.mixingTo or entry.mixBlend ~= MixBlend.add then self:computeHold(entry) end
|
||||
entry = entry.mixingTo
|
||||
until not entry
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
@ -925,57 +907,57 @@ end
|
||||
function AnimationState:computeHold(entry)
|
||||
local to = entry.mixingTo
|
||||
local timelines = entry.animation.timelines
|
||||
local timelinesCount = #entry.animation.timelines
|
||||
local timelineMode = entry.timelineMode
|
||||
local timelineHoldMix = entry.timelineHoldMix
|
||||
local propertyIDs = self.propertyIDs
|
||||
|
||||
if to and to.holdPrevious then
|
||||
local i = 1
|
||||
while i <= timelinesCount do
|
||||
local id = "" .. timelines[i]:getPropertyId()
|
||||
if propertyIDs[id] == nil then
|
||||
propertyIDs[id] = id
|
||||
timelineMode[i] = HOLD_FIRST
|
||||
else
|
||||
timelineMode[i] = HOLD_SUBSEQUENT
|
||||
for i,timeline in ipairs(timelines) do
|
||||
local mode = HOLD_SUBSEQUENT
|
||||
for _,id in ipairs(timeline.propertyIds) do
|
||||
if not propertyIDs[id] then
|
||||
propertyIDs[id] = true
|
||||
mode = HOLD_FIRST
|
||||
end
|
||||
end
|
||||
timelineMode[i] = mode
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local i = 1
|
||||
local skip
|
||||
while i <= timelinesCount do
|
||||
local id = "" .. timelines[i]:getPropertyId()
|
||||
if propertyIDs[id] then
|
||||
timelineMode[i] = SUBSEQUENT
|
||||
else
|
||||
propertyIDs[id] = id
|
||||
local timeline = timelines[i]
|
||||
if to == nil or timeline.type == Animation.TimelineType.attachment
|
||||
or timeline.type == Animation.TimelineType.drawOrder
|
||||
or timeline.type == Animation.TimelineType.event
|
||||
or not to.animation:hasTimeline(id) then
|
||||
timelineMode[i] = FIRST
|
||||
else
|
||||
local next = to.mixingTo
|
||||
skip = false
|
||||
while next do
|
||||
if not next.animation:hasTimeline(id) then
|
||||
if entry.mixDuration > 0 then
|
||||
timelineMode[i] = HOLD_MIX
|
||||
timelineHoldMix[i] = next
|
||||
skip = true
|
||||
break
|
||||
end
|
||||
end
|
||||
next = next.mixingTo
|
||||
end
|
||||
if not skip then timelineMode[i] = HOLD_FIRST end
|
||||
for i,timeline in ipairs(timelines) do
|
||||
local ids = timeline.propertyIds
|
||||
local added = false
|
||||
for _,id in ipairs(ids) do
|
||||
if not propertyIDs[id] then
|
||||
propertyIDs[id] = true
|
||||
added = true
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
if not added then
|
||||
timelineMode[i] = SUBSEQUENT
|
||||
elseif not to
|
||||
or timeline.type == Animation.TimelineType.attachment
|
||||
or timeline.type == Animation.TimelineType.drawOrder
|
||||
or timeline.type == Animation.TimelineType.event
|
||||
or not to.animation:hasTimeline(ids) then
|
||||
timelineMode[i] = FIRST
|
||||
else
|
||||
local next = to.mixingTo
|
||||
local set
|
||||
while next do
|
||||
if not next.animation:hasTimeline(ids) then
|
||||
if next.mixDuration > 0 then
|
||||
timelineMode[i] = HOLD_MIX
|
||||
timelineHoldMix[i] = next
|
||||
set = true
|
||||
end
|
||||
break
|
||||
end
|
||||
next = next.mixingTo
|
||||
end
|
||||
if not set then timelineMode[i] = HOLD_FIRST end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1,104 +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 Atlas = {}
|
||||
|
||||
function Atlas.parse(atlasPath, atlasBase)
|
||||
local function parseIntTuple4( l )
|
||||
local a,b,c,d = string.match( l , " ? ?%a+: ([+-]?%d+), ?([+-]?%d+), ?([+-]?%d+), ?([+-]?%d+)" )
|
||||
a,b,c,d = tonumber( a ), tonumber( b ), tonumber( c ), tonumber( d )
|
||||
return a and b and c and d and {a, b, c ,d}
|
||||
end
|
||||
|
||||
local function parseIntTuple2( l )
|
||||
local a,b = string.match( l , " ? ?%a+: ([+-]?%d+), ?([+-]?%d+)" )
|
||||
a,b = tonumber( a ), tonumber( b )
|
||||
return a and b and {a, b}
|
||||
end
|
||||
|
||||
if not atlasPath then
|
||||
error("Error: " .. atlasPath .. ".atlas" .. " doesn't exist!", 2)
|
||||
return nil
|
||||
end
|
||||
|
||||
local atlasLines = spine.utils.readFile( atlasPath, atlasBase )
|
||||
if not atlasLines then
|
||||
error("Error: " .. atlasPath .. ".atlas" .. " unable to read!", 2)
|
||||
return nil
|
||||
end
|
||||
|
||||
local pages = {}
|
||||
|
||||
|
||||
local it = string.gmatch(atlasLines, "(.-)\r?\n") -- iterate over lines
|
||||
for l in it do
|
||||
if #l == 0 then
|
||||
l = it()
|
||||
if l then
|
||||
local page = { name = l }
|
||||
l = it()
|
||||
page.size = parseIntTuple2( l )
|
||||
if page.size then
|
||||
l = it()
|
||||
end
|
||||
page.format = string.match( l, "%a+: (.+)" )
|
||||
page.filter = {string.match( it(), "%a+: (.+),(.+)" )}
|
||||
page.wrap = string.match( it(), "%a+: (.+)" )
|
||||
page.regions = {}
|
||||
table.insert( pages, page )
|
||||
else
|
||||
break
|
||||
end
|
||||
else
|
||||
local region = {name = l}
|
||||
|
||||
region.rotate = string.match( it(), "%a+: (.+)" ) == "true"
|
||||
region.xy = parseIntTuple2( it() )
|
||||
region.size = parseIntTuple2( it() )
|
||||
l = it()
|
||||
region.splits = parseIntTuple4(l)
|
||||
if region.splits then
|
||||
l = it()
|
||||
region.pad = parseIntTuple4(l)
|
||||
if region.pad then
|
||||
l = it()
|
||||
end
|
||||
end
|
||||
region.orig = parseIntTuple2( l )
|
||||
region.offset = parseIntTuple2( it() )
|
||||
region.index = tonumber( string.match( it() , "%a+: ([+-]?%d+)" ) )
|
||||
|
||||
table.insert( pages[#pages].regions, region )
|
||||
end
|
||||
end
|
||||
|
||||
return pages
|
||||
end
|
||||
|
||||
return Atlas
|
||||
@ -27,6 +27,8 @@
|
||||
-- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local TransformMode = require "spine-lua.TransformMode"
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local math_rad = math.rad
|
||||
local math_deg = math.deg
|
||||
@ -37,19 +39,6 @@ local math_sqrt = math.sqrt
|
||||
local math_abs = math.abs
|
||||
local math_pi = math.pi
|
||||
|
||||
local TransformMode = require "spine-lua.TransformMode"
|
||||
|
||||
function math.sign(x)
|
||||
if x < 0 then
|
||||
return -1
|
||||
elseif x > 0 then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local math_sign = math.sign
|
||||
|
||||
local Bone = {}
|
||||
Bone.__index = Bone
|
||||
|
||||
@ -64,7 +53,6 @@ function Bone.new (data, skeleton, parent)
|
||||
children = { },
|
||||
x = 0, y = 0, rotation = 0, scaleX = 1, scaleY = 1, shearX = 0, shearY = 0,
|
||||
ax = 0, ay = 0, arotation = 0, ascaleX = 0, ascaleY = 0, ashearX = 0, ashearY = 0,
|
||||
appliedValid = false,
|
||||
|
||||
a = 0, b = 0, worldX = 0, -- a b x
|
||||
c = 0, d = 0, worldY = 0, -- c d y
|
||||
@ -78,7 +66,7 @@ function Bone.new (data, skeleton, parent)
|
||||
end
|
||||
|
||||
function Bone:update ()
|
||||
self:updateWorldTransformWith(self.x, self.y, self.rotation, self.scaleX, self.scaleY, self.shearX, self.shearY)
|
||||
self:updateWorldTransformWith(self.ax, self.ay, self.arotation, self.ascaleX, self.ascaleY, self.ashearX, self.ashearY)
|
||||
end
|
||||
|
||||
function Bone:updateWorldTransform ()
|
||||
@ -93,13 +81,12 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
|
||||
self.ascaleY = scaleY
|
||||
self.ashearX = shearX
|
||||
self.ashearY = shearY
|
||||
self.appliedValid = true
|
||||
|
||||
local sx = self.skeleton.scaleX
|
||||
local sy = self.skeleton.scaleY
|
||||
|
||||
local parent = self.parent
|
||||
if parent == nil then
|
||||
if not parent then
|
||||
local rotationY = rotation + 90 + shearY
|
||||
local rotationRad = math_rad(rotation + shearX)
|
||||
local rotationYRad = math_rad(rotationY)
|
||||
@ -225,7 +212,7 @@ end
|
||||
|
||||
function Bone:updateAppliedTransform ()
|
||||
local parent = self.parent
|
||||
if parent == nil then
|
||||
if not parent then
|
||||
self.ax = self.worldX
|
||||
self.ay = self.worldY
|
||||
self.arotation = math_deg(math_atan2(self.c, self.a))
|
||||
@ -268,15 +255,11 @@ function Bone:updateAppliedTransform ()
|
||||
end
|
||||
|
||||
function Bone:worldToLocal (world)
|
||||
local a = self.a
|
||||
local b = self.b
|
||||
local c = self.c
|
||||
local d = self.d
|
||||
local invDet = 1 / (a * d - b * c)
|
||||
local invDet = 1 / (self.a * self.d - self.b * self.c)
|
||||
local x = world[1] - self.worldX
|
||||
local y = world[2] - self.worldY
|
||||
world[1] = (x * d * invDet - y * b * invDet)
|
||||
world[2] = (y * a * invDet - x * c * invDet)
|
||||
world[1] = x * self.d * invDet - y * self.b * invDet
|
||||
world[2] = y * self.a * invDet - x * self.c * invDet
|
||||
return world
|
||||
end
|
||||
|
||||
@ -313,7 +296,6 @@ function Bone:rotateWorld (degrees)
|
||||
self.b = cos * b - sin * d
|
||||
self.c = sin * a + cos * c
|
||||
self.d = sin * b + cos * d
|
||||
self.appliedValid = false
|
||||
end
|
||||
|
||||
return Bone
|
||||
|
||||
@ -76,6 +76,7 @@ function IkConstraint:apply ()
|
||||
end
|
||||
|
||||
function IkConstraint:update ()
|
||||
if self.mix == 0 then return end
|
||||
local target = self.target
|
||||
local bones = self.bones
|
||||
local boneCount = #bones
|
||||
@ -87,9 +88,7 @@ function IkConstraint:update ()
|
||||
end
|
||||
|
||||
function IkConstraint:apply1 (bone, targetX, targetY, compress, stretch, uniform, alpha)
|
||||
if not bone.appliedValid then bone:updateAppliedTransform() end
|
||||
local p = bone.parent
|
||||
|
||||
local pa = p.a
|
||||
local pb = p.b
|
||||
local pc = p.c
|
||||
@ -148,12 +147,6 @@ function IkConstraint:apply1 (bone, targetX, targetY, compress, stretch, uniform
|
||||
end
|
||||
|
||||
function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch, softness, alpha)
|
||||
if alpha == 0 then
|
||||
child:updateWorldTransform()
|
||||
return
|
||||
end
|
||||
if not parent.appliedValid then parent:updateAppliedTransform() end
|
||||
if not child.appliedValid then child:updateAppliedTransform() end
|
||||
local px = parent.ax
|
||||
local py = parent.ay
|
||||
local psx = parent.ascaleX
|
||||
|
||||
@ -36,7 +36,7 @@ local AttachmentType = require "spine-lua.attachments.AttachmentType"
|
||||
local PathConstraintData = require "spine-lua.PathConstraintData"
|
||||
local utils = require "spine-lua.utils"
|
||||
local math_pi = math.pi
|
||||
local math_pi2 = math.pi * 2
|
||||
local math_pi2 = math_pi * 2
|
||||
local math_atan2 = math.atan2
|
||||
local math_sqrt = math.sqrt
|
||||
local math_acos = math.acos
|
||||
@ -51,10 +51,10 @@ local math_max = math.max
|
||||
local PathConstraint = {}
|
||||
PathConstraint.__index = PathConstraint
|
||||
|
||||
PathConstraint.NONE = -1
|
||||
PathConstraint.BEFORE = -2
|
||||
PathConstraint.AFTER = -3
|
||||
PathConstraint.epsilon = 0.00001
|
||||
local NONE = -1
|
||||
local BEFORE = -2
|
||||
local AFTER = -3
|
||||
local epsilon = 0.00001
|
||||
|
||||
function PathConstraint.new (data, skeleton)
|
||||
if not data then error("data cannot be nil", 2) end
|
||||
@ -66,8 +66,9 @@ function PathConstraint.new (data, skeleton)
|
||||
target = skeleton:findSlot(data.target.name),
|
||||
position = data.position,
|
||||
spacing = data.spacing,
|
||||
rotateMix = data.rotateMix,
|
||||
translateMix = data.translateMix,
|
||||
mixRotate = data.mixRotate,
|
||||
mixX = data.mixX,
|
||||
mixY = data.mixY,
|
||||
spaces = {},
|
||||
positions = {},
|
||||
world = {},
|
||||
@ -85,81 +86,113 @@ function PathConstraint.new (data, skeleton)
|
||||
return self
|
||||
end
|
||||
|
||||
function PathConstraint:apply ()
|
||||
self:update()
|
||||
end
|
||||
|
||||
function PathConstraint:update ()
|
||||
local attachment = self.target.attachment
|
||||
if not attachment or not (attachment.type == AttachmentType.path) then return end
|
||||
|
||||
local rotateMix = self.rotateMix
|
||||
local translateMix = self.translateMix
|
||||
local translate = translateMix > 0
|
||||
local rotate = rotateMix > 0
|
||||
if not translate and not rotate then return end
|
||||
if not attachment or attachment.type ~= AttachmentType.path then return end
|
||||
|
||||
local mixRotate = self.mixRotate
|
||||
local mixX = self.mixX
|
||||
local mixY = self.mixY
|
||||
if mixRotate == 0 and mixX == 0 and mixY == 0 then return end
|
||||
|
||||
local data = self.data
|
||||
local percentSpacing = data.spacingMode == PathConstraintData.SpacingMode.percent
|
||||
local rotateMode = data.rotateMode
|
||||
local tangents = rotateMode == PathConstraintData.RotateMode.tangent
|
||||
local scale = rotateMode == PathConstraintData.RotateMode.chainscale
|
||||
|
||||
local bones = self.bones
|
||||
local boneCount = #bones
|
||||
local spacesCount = boneCount + 1
|
||||
if tangents then spacesCount = boneCount end
|
||||
local spacesCount = boneCount
|
||||
if tangents then spacesCount = spacesCount + 1 end
|
||||
local spaces = utils.setArraySize(self.spaces, spacesCount)
|
||||
local lengths = nil
|
||||
if scale then lengths = Utils.setArraySize(this.lengths, boneCount) end
|
||||
local spacing = self.spacing
|
||||
if scale or not percentSpacing then
|
||||
if scale then lengths = utils.setArraySize(self.lengths, boneCount) end
|
||||
local lengthSpacing = data.spacingMode == PathConstraintData.SpacingMode.length
|
||||
local i = 0
|
||||
local n = spacesCount - 1
|
||||
while i < n do
|
||||
local bone = bones[i + 1]
|
||||
local setupLength = bone.data.length
|
||||
if setupLength < PathConstraint.epsilon then
|
||||
if scale then lengths[i + 1] = 0 end
|
||||
i = i + 1
|
||||
spaces[i + 1] = 0
|
||||
elseif percentSpacing then
|
||||
if scale then
|
||||
|
||||
if data.spacingMode == PathConstraintData.SpacingMode.percent then
|
||||
if scale then
|
||||
local i = 0
|
||||
local n = spacesCount - 1
|
||||
while i < n do
|
||||
local bone = bones[i]
|
||||
local setupLength = bone.data.length
|
||||
if setupLength < epsilon then
|
||||
lengths[i] = 0
|
||||
else
|
||||
local x = setupLength * bone.a
|
||||
local y = setupLength * bone.c
|
||||
local length = math_sqrt(x * x + y * y)
|
||||
lengths[i + 1] = length
|
||||
lengths[i] = math_sqrt(x * x + y * y)
|
||||
end
|
||||
i = i + 1
|
||||
spaces[i + 1] = spacing
|
||||
end
|
||||
end
|
||||
local i = 1
|
||||
while i < spacesCount do
|
||||
spaces[i] = spacing
|
||||
i = i + 1
|
||||
end
|
||||
elseif data.spacingMode == PathConstraintData.SpacingMode.proportional then
|
||||
local sum = 0
|
||||
local i = 0
|
||||
while i < boneCount do
|
||||
local bone = bones[i]
|
||||
local setupLength = bone.data.length
|
||||
if setupLength < epsilon then
|
||||
if scale then lengths[i] = 0 end
|
||||
i = i + 1
|
||||
spaces[i] = spacing
|
||||
else
|
||||
local x = setupLength * bone.a
|
||||
local x = setupLength * bone.a
|
||||
local y = setupLength * bone.c
|
||||
local length = math_sqrt(x * x + y * y)
|
||||
if scale then lengths[i + 1] = length end
|
||||
if scale then lengths[i] = length end
|
||||
i = i + 1
|
||||
spaces[i] = length
|
||||
sum = sum + length
|
||||
end
|
||||
end
|
||||
if sum > 0 then
|
||||
sum = spacesCount / sum * spacing
|
||||
local i = 1
|
||||
while i < spacesCount do
|
||||
spaces[i] = spaces[i] * sum
|
||||
i = i + 1
|
||||
if lengthSpacing then
|
||||
spaces[i + 1] = (setupLength + spacing) * length / setupLength
|
||||
else
|
||||
spaces[i + 1] = spacing * length / setupLength
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local lengthSpacing = data.spacingMode == PathConstraintData.SpacingMode.length
|
||||
local i = 1
|
||||
while i < spacesCount do
|
||||
spaces[i + 1] = spacing
|
||||
i = i + 1
|
||||
local n = spacesCount - 1
|
||||
while i < n do
|
||||
local bone = bones[i]
|
||||
local setupLength = bone.data.length
|
||||
if setupLength < epsilon then
|
||||
if scale then lengths[i] = 0 end
|
||||
i = i + 1
|
||||
spaces[i] = spacing
|
||||
else
|
||||
local x = setupLength * bone.a
|
||||
local y = setupLength * bone.c
|
||||
local length = math_sqrt(x * x + y * y)
|
||||
if scale then lengths[i] = length end
|
||||
i = i + 1
|
||||
local s
|
||||
if lengthSpacing then
|
||||
s = setupLength + spacing
|
||||
else
|
||||
s = spacing
|
||||
end
|
||||
spaces[i] = s * length / setupLength
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local positions = self:computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PathConstraintData.PositionMode.percent, percentSpacing)
|
||||
local positions = self:computeWorldPositions(attachment, spacesCount, tangents)
|
||||
local boneX = positions[1]
|
||||
local boneY = positions[2]
|
||||
local offsetRotation = data.offsetRotation
|
||||
local tip = false
|
||||
if offsetRotation == 0 then
|
||||
tip = rotateMode == PathConstraintData.RotateMode.chain
|
||||
tip = data.rotateMode == PathConstraintData.RotateMode.chain
|
||||
else
|
||||
tip = false
|
||||
local p = self.target.bone
|
||||
@ -174,8 +207,8 @@ function PathConstraint:update ()
|
||||
local p = 3
|
||||
while i < boneCount do
|
||||
local bone = bones[i + 1]
|
||||
bone.worldX = bone.worldX + (boneX - bone.worldX) * translateMix
|
||||
bone.worldY = bone.worldY + (boneY - bone.worldY) * translateMix
|
||||
bone.worldX = bone.worldX + (boneX - bone.worldX) * mixX
|
||||
bone.worldY = bone.worldY + (boneY - bone.worldY) * mixY
|
||||
local x = positions[p + 1]
|
||||
local y = positions[p + 2]
|
||||
local dx = x - boneX
|
||||
@ -183,14 +216,14 @@ function PathConstraint:update ()
|
||||
if scale then
|
||||
local length = lengths[i + 1]
|
||||
if length ~= 0 then
|
||||
local s = (math_sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1
|
||||
local s = (math_sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1
|
||||
bone.a = bone.a * s
|
||||
bone.c = bone.c * s
|
||||
end
|
||||
end
|
||||
boneX = x
|
||||
boneY = y
|
||||
if rotate then
|
||||
if mixRotate then
|
||||
local a = bone.a
|
||||
local b = bone.b
|
||||
local c = bone.c
|
||||
@ -210,8 +243,8 @@ function PathConstraint:update ()
|
||||
cos = math_cos(r)
|
||||
sin = math_sin(r)
|
||||
local length = bone.data.length
|
||||
boneX = boneX + (length * (cos * a - sin * c) - dx) * rotateMix
|
||||
boneY = boneY + (length * (sin * a + cos * c) - dy) * rotateMix
|
||||
boneX = boneX + (length * (cos * a - sin * c) - dx) * mixRotate
|
||||
boneY = boneY + (length * (sin * a + cos * c) - dy) * mixRotate
|
||||
else
|
||||
r = r + offsetRotation
|
||||
end
|
||||
@ -220,21 +253,21 @@ function PathConstraint:update ()
|
||||
elseif r < -math_pi then
|
||||
r = r + math_pi2
|
||||
end
|
||||
r = r * rotateMix
|
||||
r = r * mixRotate
|
||||
cos = math_cos(r)
|
||||
sin = math.sin(r)
|
||||
sin = math_sin(r)
|
||||
bone.a = cos * a - sin * c
|
||||
bone.b = cos * b - sin * d
|
||||
bone.c = sin * a + cos * c
|
||||
bone.d = sin * b + cos * d
|
||||
end
|
||||
bone.appliedValid = false
|
||||
bone:updateAppliedTransform()
|
||||
i = i + 1
|
||||
p = p + 3
|
||||
end
|
||||
end
|
||||
|
||||
function PathConstraint:computeWorldPositions (path, spacesCount, tangents, percentPosition, percentSpacing)
|
||||
function PathConstraint:computeWorldPositions (path, spacesCount, tangents)
|
||||
local target = self.target
|
||||
local position = self.position
|
||||
local spaces = self.spaces
|
||||
@ -250,20 +283,20 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
||||
local lengths = path.lengths
|
||||
if closed then curveCount = curveCount - 1 else curveCount = curveCount - 2 end
|
||||
local pathLength = lengths[curveCount + 1]
|
||||
if percentPosition then position = position * pathLength end
|
||||
if percentSpacing then
|
||||
i = 1
|
||||
while i < spacesCount do
|
||||
spaces[i + 1] = spaces[i + 1] * pathLength
|
||||
i = i + 1
|
||||
end
|
||||
if self.data.positionMode == PathConstraintData.PositionMode.percent then position = position * pathLength end
|
||||
|
||||
local multiplier = 1
|
||||
if self.data.spacingMode == PathConstraintData.SpacingMode.percent then
|
||||
multiplier = pathLength
|
||||
elseif self.data.spacingMode == PathConstraintData.SpacingMode.proportional then
|
||||
multiplier = pathLength / spacesCount
|
||||
end
|
||||
world = utils.setArraySize(self.world, 8)
|
||||
i = 0
|
||||
local o = 0
|
||||
local curve = 0
|
||||
while i < spacesCount do
|
||||
local space = spaces[i + 1]
|
||||
local space = spaces[i + 1] * multiplier
|
||||
position = position + space
|
||||
local p = position
|
||||
|
||||
@ -389,17 +422,14 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
||||
i = i + 1
|
||||
w = w + 6
|
||||
end
|
||||
if percentPosition then
|
||||
position = position * pathLength
|
||||
else
|
||||
position = position * pathLength / path.lengths[curveCount]
|
||||
end
|
||||
if percentSpacing then
|
||||
i = 1
|
||||
while i < spacesCount do
|
||||
spaces[i + 1] = spaces[i + 1] * pathLength
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if self.data.positionMode == PathConstraintData.PositionMode.percent then position = position * pathLength end
|
||||
|
||||
local multiplier = 1
|
||||
if self.data.spacingMode == PathConstraintData.SpacingMode.percent then
|
||||
multiplier = pathLength
|
||||
elseif self.data.spacingMode == PathConstraintData.SpacingMode.proportional then
|
||||
multiplier = pathLength / spacesCount
|
||||
end
|
||||
|
||||
local segments = self.segments
|
||||
@ -409,7 +439,7 @@ function PathConstraint:computeWorldPositions (path, spacesCount, tangents, perc
|
||||
local curve = 0
|
||||
local segment = 0
|
||||
while i < spacesCount do
|
||||
local space = spaces[i + 1]
|
||||
local space = spaces[i + 1] * multiplier
|
||||
position = position + space
|
||||
local p = position
|
||||
|
||||
|
||||
@ -43,8 +43,9 @@ function PathConstraintData.new (name)
|
||||
offsetRotation = 0,
|
||||
position = 0,
|
||||
spacing = 0,
|
||||
rotateMix = 0,
|
||||
translateMix = 0
|
||||
mixRotate = 0,
|
||||
mixX = 0,
|
||||
mixY = 0
|
||||
}
|
||||
|
||||
return self
|
||||
@ -58,7 +59,8 @@ PathConstraintData.PositionMode = {
|
||||
PathConstraintData.SpacingMode = {
|
||||
length = 0,
|
||||
fixed = 1,
|
||||
percent = 2
|
||||
percent = 2,
|
||||
proportional = 3
|
||||
}
|
||||
|
||||
PathConstraintData.RotateMode = {
|
||||
|
||||
@ -59,7 +59,6 @@ function Skeleton.new (data)
|
||||
transformConstraints = {},
|
||||
pathConstraints = {},
|
||||
_updateCache = {},
|
||||
updateCacheReset = {},
|
||||
skin = nil,
|
||||
color = Color.newWith(1, 1, 1, 1),
|
||||
time = 0,
|
||||
@ -110,7 +109,6 @@ end
|
||||
function Skeleton:updateCache ()
|
||||
local updateCache = {}
|
||||
self._updateCache = updateCache
|
||||
self.updateCacheReset = {}
|
||||
|
||||
local bones = self.bones
|
||||
for _, bone in ipairs(bones) do
|
||||
@ -122,11 +120,11 @@ function Skeleton:updateCache ()
|
||||
local skinBones = self.skin.bones
|
||||
for i, boneData in ipairs(skinBones) do
|
||||
local bone = bones[boneData.index]
|
||||
while bone do
|
||||
repeat
|
||||
bone.sorted = false
|
||||
bone.active = true
|
||||
bone = bone.parent
|
||||
end
|
||||
until not bone
|
||||
end
|
||||
end
|
||||
|
||||
@ -196,22 +194,18 @@ function Skeleton:sortIkConstraint (constraint)
|
||||
local parent = constrained[1]
|
||||
self:sortBone(parent)
|
||||
|
||||
if #constrained > 1 then
|
||||
if #constrained == 1 then
|
||||
table_insert(self._updateCache, constraint)
|
||||
self:sortReset(parent.children)
|
||||
else
|
||||
local child = constrained[#constrained]
|
||||
local contains = false
|
||||
for _, updatable in ipairs(self._updateCache) do
|
||||
if updatable == child then
|
||||
contains = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not contains then table_insert(self.updateCacheReset, child) end
|
||||
self:sortBone(child)
|
||||
|
||||
table_insert(self._updateCache, constraint)
|
||||
|
||||
self:sortReset(parent.children)
|
||||
child.sorted = true
|
||||
end
|
||||
|
||||
table_insert(self._updateCache, constraint)
|
||||
|
||||
self:sortReset(parent.children)
|
||||
constrained[#constrained].sorted = true
|
||||
end
|
||||
|
||||
function Skeleton:sortPathConstraint(constraint)
|
||||
@ -266,7 +260,7 @@ function Skeleton:sortTransformConstraint(constraint)
|
||||
break
|
||||
end
|
||||
end
|
||||
if not contains then table_insert(self.updateCacheReset, child) end
|
||||
self:sortBone(child)
|
||||
end
|
||||
else
|
||||
for _,bone in ipairs(constrained) do
|
||||
@ -279,7 +273,6 @@ function Skeleton:sortTransformConstraint(constraint)
|
||||
for _,bone in ipairs(constrained) do
|
||||
self:sortReset(bone.children)
|
||||
end
|
||||
|
||||
for _,bone in ipairs(constrained) do
|
||||
bone.sorted = true
|
||||
end
|
||||
@ -333,8 +326,7 @@ end
|
||||
|
||||
-- Updates the world transform for each bone and applies IK constraints.
|
||||
function Skeleton:updateWorldTransform ()
|
||||
local updateCacheReset = self.updateCacheReset
|
||||
for _,bone in ipairs(updateCacheReset) do
|
||||
for _,bone in ipairs(self.bones) do
|
||||
bone.ax = bone.x
|
||||
bone.ay = bone.y
|
||||
bone.arotation = bone.rotation
|
||||
@ -342,11 +334,9 @@ function Skeleton:updateWorldTransform ()
|
||||
bone.ascaleY = bone.scaleY
|
||||
bone.ashearX = bone.shearX
|
||||
bone.ashearY = bone.shearY
|
||||
bone.appliedValid = true
|
||||
end
|
||||
|
||||
local updateCache = self._updateCache
|
||||
for _, updatable in ipairs(updateCache) do
|
||||
for _, updatable in ipairs(self._updateCache) do
|
||||
updatable:update()
|
||||
end
|
||||
end
|
||||
@ -372,10 +362,12 @@ function Skeleton:setBonesToSetupPose ()
|
||||
local transformConstraints = self.transformConstraints
|
||||
for _, constraint in ipairs(transformConstraints) do
|
||||
local data = constraint.data
|
||||
constraint.rotateMix = data.rotateMix
|
||||
constraint.translateMix = data.translateMix
|
||||
constraint.scaleMix = data.scaleMix
|
||||
constraint.shearMix = data.shearMix
|
||||
constraint.mixRotate = data.mixRotate
|
||||
constraint.mixX = data.mixX
|
||||
constraint.mixY = data.mixY
|
||||
constraint.mixScaleX = data.mixScaleX
|
||||
constraint.mixScaleY = data.mixScaleY
|
||||
constraint.mixShearY = data.mixShearY
|
||||
end
|
||||
|
||||
local pathConstraints = self.pathConstraints
|
||||
@ -383,8 +375,9 @@ function Skeleton:setBonesToSetupPose ()
|
||||
local data = constraint.data
|
||||
constraint.position = data.position
|
||||
constraint.spacing = data.spacing
|
||||
constraint.rotateMix = data.rotateMix
|
||||
constraint.translateMix = data.translateMix
|
||||
constraint.mixRotate = data.mixRotate
|
||||
constraint.mixX = data.mixX
|
||||
constraint.mixY = data.mixY
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -558,9 +558,9 @@ function SkeletonJson.new (attachmentLoader)
|
||||
for timelineName,timelineMap in pairs(slotMap) do
|
||||
if not timelineMap then
|
||||
elseif timelineName == "attachment" then
|
||||
local timeline = Animation.AttachmentTimeline.new(#timelineMap, slotIndex)
|
||||
local timeline = Animation.AttachmentTimeline.new(#timelineMap, #timelineMap, slotIndex)
|
||||
for i,keyMap in ipairs(timelineMap) do
|
||||
timeline:setFrame(i + 1, getValue(keyMap, "time", 0), keyMap["name"])
|
||||
timeline:setFrame(i - 1, getValue(keyMap, "time", 0), keyMap["name"])
|
||||
end
|
||||
table_insert(timelines, timeline)
|
||||
elseif timelineName == "rgba" then
|
||||
@ -765,7 +765,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, scale))
|
||||
elseif timelineName == "scale" then
|
||||
local timeline = Animation.ScaleTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
|
||||
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 1, 1))
|
||||
table_insert(timelines, readTimeline2(timelineMap, timeline, "x", "y", 1, 1))
|
||||
elseif timelineName == "scalex" then
|
||||
local timeline = Animation.ScaleXTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
|
||||
@ -774,7 +774,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
table_insert(timelines, readTimeline1(timelineMap, timeline, 1, 1))
|
||||
elseif timelineName == "shear" then
|
||||
local timeline = Animation.ShearTimeline.new(#timelineMap, #timelineMap * 2, boneIndex)
|
||||
table_insert(timelines, readTimeline2(timelineMap, "x", "y", 0, 1))
|
||||
table_insert(timelines, readTimeline2(timelineMap, timeline, "x", "y", 0, 1))
|
||||
elseif timelineName == "shearx" then
|
||||
local timeline = Animation.ShearXTimeline.new(#timelineMap, #timelineMap, boneIndex)
|
||||
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, 1))
|
||||
@ -901,7 +901,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
if map.path then
|
||||
for constraintName,constraintMap in pairs(map.path) do
|
||||
local constraint, constraintIndex = -1
|
||||
for i,other in pairs(skeletonData.transformConstraints) do
|
||||
for i,other in pairs(skeletonData.pathConstraints) do
|
||||
if other.name == constraintName then
|
||||
constraintIndex = i
|
||||
constraint = other
|
||||
@ -914,12 +914,12 @@ function SkeletonJson.new (attachmentLoader)
|
||||
if timelineName == "position" then
|
||||
local timeline = Animation.PathConstraintPositionTimeline.new(#timelineMap, #timelineMap, constraintIndex)
|
||||
local timelineScale = 1
|
||||
if constraint.positionMode == PositionMode.fixed then timelineScale = scale end
|
||||
if constraint.positionMode == PathConstraintData.PositionMode.fixed then timelineScale = scale end
|
||||
table_insert(timelines, readTimeline1(timelineMap, timeline, 0, timelineScale))
|
||||
elseif timelineName == "spacing" then
|
||||
local timeline = Animation.PathConstraintSpacingTimeline.new(#timelineMap, #timelineMap, constraintIndex)
|
||||
local timelineScale = 1
|
||||
if data.spacingMode == SpacingMode.Length or data.spacingMode == SpacingMode.Fixed then timelineScale = scale end
|
||||
if data.spacingMode == PathConstraintData.SpacingMode.Length or data.spacingMode == PathConstraintData.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)
|
||||
@ -978,6 +978,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
if weighted then deformLength = math_floor(deformLength / 3) * 2 end
|
||||
|
||||
local timeline = Animation.DeformTimeline.new(#timelineMap, #timelineMap, slotIndex, attachment)
|
||||
local time = getValue(keyMap, "time", 0)
|
||||
local bezier = 0
|
||||
for i,keyMap in ipairs(timelineMap) do
|
||||
local deform = nil
|
||||
@ -1007,7 +1008,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
end
|
||||
end
|
||||
local frame = i - 1
|
||||
timeline:setFrame(frame, time, mixRotate, mixX, mixY)
|
||||
timeline:setFrame(frame, time, deform)
|
||||
local nextMap = timelineMap[frame + 1]
|
||||
if not nextMap then
|
||||
timeline:shrink(bezier)
|
||||
@ -1172,15 +1173,15 @@ function SkeletonJson.new (attachmentLoader)
|
||||
|
||||
readCurve = function (curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale)
|
||||
if curve == "stepped" then
|
||||
if value ~= 0 then timeline.setStepped(frame) end
|
||||
if value ~= 0 then timeline:setStepped(frame) end
|
||||
return bezier
|
||||
end
|
||||
local i = value * 4
|
||||
local i = value * 4 + 1
|
||||
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)
|
||||
timeline:setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2)
|
||||
return bezier + 1
|
||||
end
|
||||
|
||||
|
||||
@ -60,9 +60,16 @@ end
|
||||
|
||||
function Slot:setAttachment (attachment)
|
||||
if self.attachment == attachment then return end
|
||||
if not attachment
|
||||
or not attachment.isVertexAttachment
|
||||
or not self.attachment
|
||||
or not self.attachment.isVertexAttachment
|
||||
or attachment.deformAttachment ~= self.attachment.deformAttachment
|
||||
then
|
||||
self.deform = {}
|
||||
end
|
||||
self.attachment = attachment
|
||||
self.attachmentTime = self.bone.skeleton.time
|
||||
self.deform = {}
|
||||
end
|
||||
|
||||
function Slot:setAttachmentTime (time)
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
-- 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
|
||||
-- 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,
|
||||
@ -28,6 +28,7 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local tonumber = tonumber
|
||||
local table_insert = table.insert
|
||||
local math_abs = math.abs
|
||||
|
||||
@ -47,7 +48,8 @@ function TextureAtlasPage.new ()
|
||||
vWrap = nil,
|
||||
texture = nil,
|
||||
width = 0,
|
||||
height = 0
|
||||
height = 0,
|
||||
pma = false
|
||||
}
|
||||
setmetatable(self, TextureAtlasPage)
|
||||
return self
|
||||
@ -73,168 +75,178 @@ function TextureAtlas:parse (atlasContent, imageLoader)
|
||||
if not atlasContent then error("atlasContent cannot be nil.", 2) end
|
||||
if not imageLoader then error("imageLoader cannot be nil.", 2) end
|
||||
|
||||
function lineIterator(s)
|
||||
if s:sub(-1)~="\n" then s=s.."\n" end
|
||||
return s:gmatch("(.-)\n")
|
||||
local readLine = atlasContent:gmatch("[ \t]*(.-)[ \t]*\r?\n")
|
||||
|
||||
local trim = function (value)
|
||||
return value:match("^%s*(.-)%s*$")
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
local index = 0
|
||||
local numLines = 0
|
||||
for line in lineIterator(atlasContent) do
|
||||
lines[numLines] = line
|
||||
numLines = numLines + 1
|
||||
end
|
||||
local entry = {}
|
||||
local readEntry = function (entry, line)
|
||||
if not line then return 0 end
|
||||
if line:len() == 0 then return 0 end
|
||||
|
||||
local readLine = function ()
|
||||
if index >= numLines then return nil end
|
||||
local line = lines[index]
|
||||
index = index + 1
|
||||
return line
|
||||
end
|
||||
|
||||
local readValue = function ()
|
||||
local line = readLine()
|
||||
local idx = line:find(":")
|
||||
if not idx then error("Invalid line: " .. line, 2) end
|
||||
return line:sub(idx + 1):match'^%s*(.*%S)' or ''
|
||||
end
|
||||
|
||||
local readTuple = function ()
|
||||
local line = readLine()
|
||||
local idx = line:find(":")
|
||||
if not idx then
|
||||
error("Invalid line: " .. line, 2)
|
||||
end
|
||||
local colon = line:find(":")
|
||||
if not colon then return 0 end
|
||||
entry[0] = trim(line:sub(1, colon))
|
||||
local lastMatch = colon + 1
|
||||
local i = 1
|
||||
local lastMatch = idx + 1
|
||||
local tuple = {}
|
||||
while i <= 3 do
|
||||
while true do
|
||||
local comma = line:find(",", lastMatch)
|
||||
if not comma then break end
|
||||
tuple[i] = line:sub(lastMatch, comma - 1):match'^%s*(.*%S)' or ''
|
||||
if not comma then
|
||||
entry[i] = trim(line:sub(lastMatch))
|
||||
return i
|
||||
end
|
||||
entry[i] = trim(line:sub(lastMatch, comma - lastMatch))
|
||||
lastMatch = comma + 1
|
||||
if i == 4 then return 4 end
|
||||
i = i + 1
|
||||
end
|
||||
tuple[i] = line:sub(lastMatch):match'^%s*(.*%S)' or ''
|
||||
return tuple
|
||||
end
|
||||
|
||||
local parseInt = function (str)
|
||||
return tonumber(str)
|
||||
local page
|
||||
local region
|
||||
|
||||
local pageFields = {}
|
||||
pageFields["size"] = function ()
|
||||
page.width = tonumber(entry[1])
|
||||
page.height = tonumber(entry[2])
|
||||
end
|
||||
pageFields["format"] = function ()
|
||||
-- page.format = Format[tuple[0]] we don't need format in Lua
|
||||
end
|
||||
pageFields["filter"] = function ()
|
||||
page.minFilter = TextureFilter[entry[1]]
|
||||
page.magFilter = TextureFilter[entry[2]]
|
||||
end
|
||||
pageFields["repeat"] = function ()
|
||||
if entry[1]:find("x") then page.uWrap = TextureWrap.Repeat end
|
||||
if entry[1]:find("y") then page.vWrap = TextureWrap.Repeat end
|
||||
end
|
||||
pageFields["pma"] = function ()
|
||||
page.pma = entry[1] == "true"
|
||||
end
|
||||
|
||||
local filterFromString = function (str)
|
||||
str = str:lower()
|
||||
if str == "nearest" then return TextureFilter.Nearest
|
||||
elseif str == "linear" then return TextureFilter.Linear
|
||||
elseif str == "mipmap" then return TextureFilter.MipMap
|
||||
elseif str == "mipmapnearestnearest" then return TextureFilter.MipMapNearestNearest
|
||||
elseif str == "mipmaplinearnearest" then return TextureFilter.MipMapLinearNearest
|
||||
elseif str == "mipmapnearestlinear" then return TextureFilter.MipMapNearestLinear
|
||||
elseif str == "mipmaplinearlinear" then return TextureFilter.MipMapLinearLinear
|
||||
else error("Unknown texture wrap: " .. str, 2)
|
||||
local regionFields = {}
|
||||
regionFields["xy"] = function () -- Deprecated, use bounds.
|
||||
region.x = tonumber(entry[1])
|
||||
region.y = tonumber(entry[2])
|
||||
end
|
||||
regionFields["size"] = function () -- Deprecated, use bounds.
|
||||
region.width = tonumber(entry[1])
|
||||
region.height = tonumber(entry[2])
|
||||
end
|
||||
regionFields["bounds"] = function ()
|
||||
region.x = tonumber(entry[1])
|
||||
region.y = tonumber(entry[2])
|
||||
region.width = tonumber(entry[3])
|
||||
region.height = tonumber(entry[4])
|
||||
end
|
||||
regionFields["offset"] = function () -- Deprecated, use offsets.
|
||||
region.offsetX = tonumber(entry[1])
|
||||
region.offsetY = tonumber(entry[2])
|
||||
end
|
||||
regionFields["orig"] = function () -- Deprecated, use offsets.
|
||||
region.originalWidth = tonumber(entry[1])
|
||||
region.originalHeight = tonumber(entry[2])
|
||||
end
|
||||
regionFields["offsets"] = function ()
|
||||
region.offsetX = tonumber(entry[1])
|
||||
region.offsetY = tonumber(entry[2])
|
||||
region.originalWidth = tonumber(entry[3])
|
||||
region.originalHeight = tonumber(entry[4])
|
||||
end
|
||||
regionFields["rotate"] = function ()
|
||||
local value = entry[1]
|
||||
if value == "true" then
|
||||
region.degrees = 90
|
||||
elseif value ~= "false" then
|
||||
region.degrees = tonumber(value)
|
||||
end
|
||||
end
|
||||
regionFields["index"] = function ()
|
||||
region.index = tonumber(entry[1])
|
||||
end
|
||||
|
||||
local page = nil
|
||||
local line = readLine()
|
||||
-- Ignore empty lines before first entry.
|
||||
while line and line:len() == 0 do
|
||||
line = readLine()
|
||||
end
|
||||
-- Header entries.
|
||||
while true do
|
||||
if not line or line:len() == 0 then break end
|
||||
if readEntry(entry, line) == 0 then break end -- Silently ignore all header fields.
|
||||
line = readLine()
|
||||
end
|
||||
|
||||
-- Page and region entries.
|
||||
local names
|
||||
local values
|
||||
while true do
|
||||
local line = readLine()
|
||||
if not line then break end
|
||||
line = line:match'^%s*(.*%S)' or ''
|
||||
if line:len() == 0 then
|
||||
page = nil
|
||||
line = readLine()
|
||||
elseif not page then
|
||||
page = TextureAtlasPage.new()
|
||||
page.name = line
|
||||
|
||||
local tuple = readTuple()
|
||||
if #tuple == 2 then
|
||||
page.width = parseInt(tuple[1])
|
||||
page.height = parseInt(tuple[2])
|
||||
tuple = readTuple()
|
||||
else
|
||||
-- We only support atlases that have the page width/height
|
||||
-- encoded in them. That way we don't rely on any special
|
||||
-- wrapper objects for images to get the page size from
|
||||
error("Atlas must specify page width/height. Please export to the latest atlas format", 2)
|
||||
page.name = trim(line)
|
||||
while true do
|
||||
line = readLine()
|
||||
if readEntry(entry, line) == 0 then break end
|
||||
local field = pageFields[entry[0]]
|
||||
if field then field() end
|
||||
end
|
||||
|
||||
tuple = readTuple()
|
||||
page.minFilter = filterFromString(tuple[1])
|
||||
page.magFilter = filterFromString(tuple[2])
|
||||
|
||||
local direction = readValue()
|
||||
page.uWrap = TextureWrap.ClampToEdge
|
||||
page.vWrap = TextureWrap.ClampToEdge
|
||||
if direction == "x" then
|
||||
page.uWrap = TextureWrap.Repeat
|
||||
elseif direction == "y" then
|
||||
page.vWrap = TextureWrap.Repeat
|
||||
elseif direction == "xy" then
|
||||
page.uWrap = TextureWrap.Repeat
|
||||
page.vWrap = TextureWrap.Repeat
|
||||
end
|
||||
|
||||
page.texture = imageLoader(line)
|
||||
-- FIXME page.texture:setFilters(page.minFilter, page.magFilter)
|
||||
-- FIXME page.texture:setWraps(page.uWrap, page.vWrap)
|
||||
page.texture = imageLoader(page.name)
|
||||
-- FIXME - Apply the filter and wrap settings to the texture.
|
||||
-- page.texture:setFilters(page.minFilter, page.magFilter)
|
||||
-- page.texture:setWraps(page.uWrap, page.vWrap)
|
||||
table_insert(self.pages, page)
|
||||
else
|
||||
local region = TextureAtlasRegion.new()
|
||||
region.name = line
|
||||
region = TextureAtlasRegion.new()
|
||||
region.page = page
|
||||
|
||||
local rotateValue = readValue()
|
||||
if rotateValue == "true" then
|
||||
region.degrees = 90
|
||||
elseif rotateValue == "false" then
|
||||
region.degrees = 0
|
||||
else
|
||||
region.degrees = tonumber(rotateValue)
|
||||
end
|
||||
if region.degrees == 90 then region.rotate = true end
|
||||
|
||||
local tuple = readTuple()
|
||||
local x = parseInt(tuple[1])
|
||||
local y = parseInt(tuple[2])
|
||||
|
||||
tuple = readTuple()
|
||||
local width = parseInt(tuple[1])
|
||||
local height = parseInt(tuple[2])
|
||||
|
||||
region.u = x / page.width
|
||||
region.v = y / page.height
|
||||
if region.rotate then
|
||||
region.u2 = (x + height) / page.width
|
||||
region.v2 = (y + width) / page.height
|
||||
else
|
||||
region.u2 = (x + width) / page.width
|
||||
region.v2 = (y + height) / page.height
|
||||
end
|
||||
|
||||
region.x = x
|
||||
region.y = y
|
||||
region.width = math_abs(width)
|
||||
region.height = math_abs(height)
|
||||
|
||||
-- Read and skip optional splits
|
||||
tuple = readTuple()
|
||||
if #tuple == 4 then
|
||||
tuple = readTuple()
|
||||
if #tuple == 4 then
|
||||
readTuple()
|
||||
region.name = line
|
||||
while true do
|
||||
line = readLine()
|
||||
local count = readEntry(entry, line)
|
||||
if count == 0 then break end
|
||||
local field = regionFields[entry[0]]
|
||||
if field then
|
||||
field()
|
||||
else
|
||||
if not names then
|
||||
names = {}
|
||||
values = {}
|
||||
end
|
||||
table_insert(names, entry[0])
|
||||
local entryValues = {}
|
||||
local i = 0
|
||||
while i < count do
|
||||
table_insert(entryValues, tonumber(entry[i + 1]))
|
||||
i = i + 1
|
||||
end
|
||||
table_insert(values, entryValues)
|
||||
end
|
||||
end
|
||||
|
||||
region.originalWidth = parseInt(tuple[1])
|
||||
region.originalHeight = parseInt(tuple[2])
|
||||
|
||||
tuple = readTuple()
|
||||
region.offsetX = parseInt(tuple[1])
|
||||
region.offsetY = parseInt(tuple[2])
|
||||
|
||||
region.index = parseInt(readValue())
|
||||
if region.originalWidth == 0 and region.originalHeight == 0 then
|
||||
region.originalWidth = region.width
|
||||
region.originalHeight = region.height
|
||||
end
|
||||
if names and #names > 0 then
|
||||
region.names = names
|
||||
region.values = values
|
||||
names = nil
|
||||
values = nil
|
||||
end
|
||||
region.u = region.x / page.width
|
||||
region.v = region.y / page.height
|
||||
if region.degrees == 90 then
|
||||
region.u2 = (region.x + region.height) / page.width
|
||||
region.v2 = (region.y + region.width) / page.height
|
||||
else
|
||||
region.u2 = (region.x + region.width) / page.width
|
||||
region.v2 = (region.y + region.height) / page.height
|
||||
end
|
||||
region.texture = page.texture
|
||||
table_insert(self.regions, region)
|
||||
end
|
||||
|
||||
@ -42,9 +42,10 @@ function TextureAtlasRegion.new ()
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.index = 0
|
||||
self.rotate = false
|
||||
self.degrees = 0
|
||||
self.texture = nil
|
||||
self.names = nil
|
||||
self.values = nil
|
||||
setmetatable(self, TextureAtlasRegion)
|
||||
|
||||
return self
|
||||
|
||||
@ -53,7 +53,7 @@ function TransformConstraint.new (data, skeleton)
|
||||
data = data,
|
||||
bones = {},
|
||||
target = nil,
|
||||
rotateMix = data.rotateMix, translateMix = data.translateMix, scaleMix = data.scaleMix, shearMix = data.shearMix,
|
||||
mixRotate = data.mixRotate, mixX = data.mixX, mixY = data.mixY, mixScaleX = data.mixScaleX, mixScaleY = data.mixScaleY, mixShearY = data.mixShearY,
|
||||
temp = { 0, 0 },
|
||||
active = false
|
||||
}
|
||||
@ -67,11 +67,9 @@ function TransformConstraint.new (data, skeleton)
|
||||
return self
|
||||
end
|
||||
|
||||
function TransformConstraint:apply ()
|
||||
self:update()
|
||||
end
|
||||
|
||||
function TransformConstraint:update ()
|
||||
if self.mixRotate == 0 and self.mixX == 0 and self.mixY == 0 and self.mixScaleX == 0 and self.mixScaleX == 0 and self.mixShearY == 0 then return end
|
||||
|
||||
if self.data.local_ then
|
||||
if self.data.relative then
|
||||
self:applyRelativeLocal()
|
||||
@ -88,10 +86,14 @@ function TransformConstraint:update ()
|
||||
end
|
||||
|
||||
function TransformConstraint:applyAbsoluteWorld ()
|
||||
local rotateMix = self.rotateMix
|
||||
local translateMix = self.translateMix
|
||||
local scaleMix = self.scaleMix
|
||||
local shearMix = self.shearMix
|
||||
local mixRotate = self.mixRotate
|
||||
local mixX = self.mixX
|
||||
local mixY = self.mixY
|
||||
local mixScaleX = self.mixScaleX
|
||||
local mixScaleY = self.mixScaleY
|
||||
local mixShearY = self.mixShearY
|
||||
local translate = mixX ~= 0 or mixY ~= 0
|
||||
|
||||
local target = self.target
|
||||
local ta = target.a
|
||||
local tb = target.b
|
||||
@ -101,10 +103,10 @@ function TransformConstraint:applyAbsoluteWorld ()
|
||||
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
|
||||
local offsetRotation = self.data.offsetRotation * degRadReflect
|
||||
local offsetShearY = self.data.offsetShearY * degRadReflect
|
||||
|
||||
local bones = self.bones
|
||||
for _, bone in ipairs(bones) do
|
||||
local modified = false
|
||||
if rotateMix ~= 0 then
|
||||
if mixRotate ~= 0 then
|
||||
local a = bone.a
|
||||
local b = bone.b
|
||||
local c = bone.c
|
||||
@ -115,45 +117,38 @@ function TransformConstraint:applyAbsoluteWorld ()
|
||||
elseif r < -math_pi then
|
||||
r = r + math_pi2
|
||||
end
|
||||
r = r * rotateMix
|
||||
r = r * mixRotate
|
||||
local cos = math_cos(r)
|
||||
local sin = math_sin(r)
|
||||
bone.a = cos * a - sin * c
|
||||
bone.b = cos * b - sin * d
|
||||
bone.c = sin * a + cos * c
|
||||
bone.d = sin * b + cos * d
|
||||
modified = true
|
||||
end
|
||||
|
||||
if translateMix ~= 0 then
|
||||
if translate then
|
||||
local temp = self.temp
|
||||
temp[1] = self.data.offsetX
|
||||
temp[2] = self.data.offsetY
|
||||
target:localToWorld(temp)
|
||||
bone.worldX = bone.worldX + (temp[1] - bone.worldX) * translateMix
|
||||
bone.worldY = bone.worldY + (temp[2] - bone.worldY) * translateMix
|
||||
modified = true
|
||||
bone.worldX = bone.worldX + (temp[1] - bone.worldX) * mixX
|
||||
bone.worldY = bone.worldY + (temp[2] - bone.worldY) * mixY
|
||||
end
|
||||
|
||||
if scaleMix > 0 then
|
||||
if mixScaleX ~= 0 then
|
||||
local s = math_sqrt(bone.a * bone.a + bone.c * bone.c)
|
||||
local ts = math_sqrt(ta * ta + tc * tc)
|
||||
if s > 0.00001 then
|
||||
s = (s + (ts - s + self.data.offsetScaleX) * scaleMix) / s
|
||||
end
|
||||
if s ~= 0 then s = (s + (math_sqrt(ta * ta + tc * tc) - s + self.data.offsetScaleX) * mixScaleX) / s end
|
||||
bone.a = bone.a * s
|
||||
bone.c = bone.c * s
|
||||
s = math_sqrt(bone.b * bone.b + bone.d * bone.d)
|
||||
ts = math_sqrt(tb * tb + td * td)
|
||||
if s > 0.00001 then
|
||||
s = (s + (ts - s + self.data.offsetScaleY) * scaleMix) / s
|
||||
end
|
||||
end
|
||||
if mixScaleY ~= 0 then
|
||||
local s = math_sqrt(bone.b * bone.b + bone.d * bone.d)
|
||||
if s ~= 0 then s = (s + (math_sqrt(tb * tb + td * td) - s + self.data.offsetScaleY) * mixScaleY) / s end
|
||||
bone.b = bone.b * s
|
||||
bone.d = bone.d * s
|
||||
modified = true
|
||||
end
|
||||
|
||||
if shearMix > 0 then
|
||||
if mixShearY > 0 then
|
||||
local b = bone.b
|
||||
local d = bone.d
|
||||
local by = math_atan2(d, b)
|
||||
@ -163,22 +158,25 @@ function TransformConstraint:applyAbsoluteWorld ()
|
||||
elseif r < -math_pi then
|
||||
r = r + math_pi2
|
||||
end
|
||||
r = by + (r + offsetShearY) * shearMix
|
||||
r = by + (r + offsetShearY) * mixShearY
|
||||
local s = math_sqrt(b * b + d * d)
|
||||
bone.b = math_cos(r) * s
|
||||
bone.d = math_sin(r) * s
|
||||
modified = true
|
||||
end
|
||||
|
||||
if modified then bone.appliedValid = false end
|
||||
bone:updateAppliedTransform()
|
||||
end
|
||||
end
|
||||
|
||||
function TransformConstraint:applyRelativeWorld ()
|
||||
local rotateMix = self.rotateMix
|
||||
local translateMix = self.translateMix
|
||||
local scaleMix = self.scaleMix
|
||||
local shearMix = self.shearMix
|
||||
local mixRotate = self.mixRotate
|
||||
local mixX = self.mixX
|
||||
local mixY = self.mixY
|
||||
local mixScaleX = self.mixScaleX
|
||||
local mixScaleY = self.mixScaleY
|
||||
local mixShearY = self.mixShearY
|
||||
local translate = mixX ~= 0 or mixY ~= 0
|
||||
|
||||
local target = self.target
|
||||
local ta = target.a
|
||||
local tb = target.b
|
||||
@ -188,11 +186,12 @@ function TransformConstraint:applyRelativeWorld ()
|
||||
if ta * td - tb * tc > 0 then degRadReflect = utils.degRad else degRadReflect = -utils.degRad end
|
||||
local offsetRotation = self.data.offsetRotation * degRadReflect
|
||||
local offsetShearY = self.data.offsetShearY * degRadReflect
|
||||
|
||||
local bones = self.bones
|
||||
for _, bone in ipairs(bones) do
|
||||
local modified = false
|
||||
|
||||
if rotateMix ~= 0 then
|
||||
if mixRotate ~= 0 then
|
||||
local a = bone.a
|
||||
local b = bone.b
|
||||
local c = bone.c
|
||||
@ -203,37 +202,36 @@ function TransformConstraint:applyRelativeWorld ()
|
||||
elseif r < -math_pi then
|
||||
r = r + math_pi2
|
||||
end
|
||||
r = r * rotateMix
|
||||
r = r * mixRotate
|
||||
local cos = math_cos(r)
|
||||
local sin = math_sin(r)
|
||||
bone.a = cos * a - sin * c
|
||||
bone.b = cos * b - sin * d
|
||||
bone.c = sin * a + cos * c
|
||||
bone.d = sin * b + cos * d
|
||||
modified = true
|
||||
end
|
||||
|
||||
if translateMix ~= 0 then
|
||||
if translate then
|
||||
local temp = self.temp
|
||||
temp[1] = self.data.offsetX
|
||||
temp[2] = self.data.offsetY
|
||||
target:localToWorld(temp)
|
||||
bone.worldX = bone.worldX + temp[1] * translateMix
|
||||
bone.worldY = bone.worldY + temp[2] * translateMix
|
||||
modified = true
|
||||
bone.worldX = bone.worldX + temp[1] * mixX
|
||||
bone.worldY = bone.worldY + temp[2] * mixY
|
||||
end
|
||||
|
||||
if scaleMix > 0 then
|
||||
local s = (math_sqrt(ta * ta + tc * tc) - 1 + self.data.offsetScaleX) * scaleMix + 1
|
||||
if mixScaleX ~= 0 then
|
||||
local s = (math_sqrt(ta * ta + tc * tc) - 1 + self.data.offsetScaleX) * mixScaleX + 1
|
||||
bone.a = bone.a * s
|
||||
bone.c = bone.c * s
|
||||
s = (math_sqrt(tb * tb + td * td) - 1 + self.data.offsetScaleY) * scaleMix + 1
|
||||
end
|
||||
if mixScaleY ~= 0 then
|
||||
local s = (math_sqrt(tb * tb + td * td) - 1 + self.data.offsetScaleY) * mixScaleY + 1
|
||||
bone.b = bone.b * s
|
||||
bone.d = bone.d * s
|
||||
modified = true
|
||||
end
|
||||
|
||||
if shearMix > 0 then
|
||||
if mixShearY > 0 then
|
||||
local r = math_atan2(td, tb) - math_atan2(tc, ta)
|
||||
if r > math_pi then
|
||||
r = r - math_pi2
|
||||
@ -242,59 +240,54 @@ function TransformConstraint:applyRelativeWorld ()
|
||||
end
|
||||
local b = bone.b
|
||||
local d = bone.d
|
||||
r = math_atan2(d, b) + (r - math_pi / 2 + offsetShearY) * shearMix
|
||||
r = math_atan2(d, b) + (r - math_pi / 2 + offsetShearY) * mixShearY
|
||||
local s = math_sqrt(b * b + d * d)
|
||||
bone.b = math_cos(r) * s
|
||||
bone.d = math_sin(r) * s
|
||||
modified = true
|
||||
end
|
||||
|
||||
if modified then bone.appliedValid = false end
|
||||
bone:updateAppliedTransform()
|
||||
end
|
||||
end
|
||||
|
||||
function TransformConstraint:applyAbsoluteLocal ()
|
||||
local rotateMix = self.rotateMix
|
||||
local translateMix = self.translateMix
|
||||
local scaleMix = self.scaleMix
|
||||
local shearMix = self.shearMix
|
||||
local mixRotate = self.mixRotate
|
||||
local mixX = self.mixX
|
||||
local mixY = self.mixY
|
||||
local mixScaleX = self.mixScaleX
|
||||
local mixScaleY = self.mixScaleY
|
||||
local mixShearY = self.mixShearY
|
||||
|
||||
local target = self.target
|
||||
if not target.appliedValid then target:updatedAppliedTransform() end
|
||||
local bones = self.bones
|
||||
for _, bone in ipairs(bones) do
|
||||
local modified = false
|
||||
if not bone.appliedValid then bone:updateAppliedTransform() end
|
||||
|
||||
local rotation = bone.arotation
|
||||
if rotateMix ~= 0 then
|
||||
if mixRotate ~= 0 then
|
||||
local r = target.arotation - rotation + self.data.offsetRotation
|
||||
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
|
||||
rotation = rotation + r * rotateMix
|
||||
rotation = rotation + r * mixRotate
|
||||
end
|
||||
|
||||
local x = bone.ax
|
||||
local y = bone.ay
|
||||
if translateMix ~= 0 then
|
||||
x = x + (target.ax - x + self.data.offsetX) * translateMix
|
||||
y = x + (target.ay - y + self.data.offsetY) * translateMix
|
||||
end
|
||||
x = x + (target.ax - x + self.data.offsetX) * mixX
|
||||
y = x + (target.ay - y + self.data.offsetY) * mixX
|
||||
|
||||
local scaleX = bone.ascaleX
|
||||
local scaleY = bone.ascaleY
|
||||
if scaleMix ~= 0 then
|
||||
if scaleX > 0.00001 then
|
||||
scaleX = (scaleX + (target.ascaleX - scaleX + self.data.offsetScaleX) * scaleMix) / scaleX
|
||||
end
|
||||
if scaleY > 0.00001 then
|
||||
scaleY = (scaleY + (target.ascaleY - scaleY + self.data.offsetScaleY) * scaleMix) / scaleY
|
||||
end
|
||||
if mixScaleX ~= 0 and scaleX ~= 0 then
|
||||
scaleX = (scaleX + (target.ascaleX - scaleX + self.data.offsetScaleX) * mixScaleX) / scaleX
|
||||
end
|
||||
if mixScaleY ~= 0 and scaleY ~= 0 then
|
||||
scaleY = (scaleY + (target.ascaleY - scaleY + self.data.offsetScaleY) * mixScaleY) / scaleY
|
||||
end
|
||||
|
||||
local shearY = bone.ashearY
|
||||
if shearMix ~= 0 then
|
||||
if mixShearY ~= 0 then
|
||||
local r = target.ashearY - shearY + self.data.offsetShearY
|
||||
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
|
||||
bone.shearY = bone.shearY + r * shearMix
|
||||
bone.shearY = bone.shearY + r * mixShearY
|
||||
end
|
||||
|
||||
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY)
|
||||
@ -302,40 +295,23 @@ function TransformConstraint:applyAbsoluteLocal ()
|
||||
end
|
||||
|
||||
function TransformConstraint:applyRelativeLocal ()
|
||||
local rotateMix = self.rotateMix
|
||||
local translateMix = self.translateMix
|
||||
local scaleMix = self.scaleMix
|
||||
local shearMix = self.shearMix
|
||||
local mixRotate = self.mixRotate
|
||||
local mixX = self.mixX
|
||||
local mixY = self.mixY
|
||||
local mixScaleX = self.mixScaleX
|
||||
local mixScaleY = self.mixScaleY
|
||||
local mixShearY = self.mixShearY
|
||||
|
||||
local target = self.target
|
||||
if not target.appliedValid then target:updateAppliedTransform() end
|
||||
|
||||
local bones = self.bones
|
||||
for _, bone in ipairs(bones) do
|
||||
if not bone.appliedValid then bone:updateAppliedTransform() end
|
||||
|
||||
local rotation = bone.arotation
|
||||
if rotateMix ~= 0 then rotation = rotation + (target.arotation + self.data.offsetRotation) * rotateMix end
|
||||
|
||||
local x = bone.ax
|
||||
local y = bone.ay
|
||||
if translateMix ~= 0 then
|
||||
x = x + (target.ax + self.data.offsetX) * translateMix
|
||||
y = y + (target.ay + self.data.offsetY) * translateMix
|
||||
end
|
||||
|
||||
local scaleX = bone.ascaleX
|
||||
local scaleY = bone.ascaleY
|
||||
if scaleMix ~= 0 then
|
||||
if scaleX > 0.00001 then
|
||||
scaleX = scaleX * (((target.ascaleX - 1 + self.data.offsetScaleX) * scaleMix) + 1)
|
||||
end
|
||||
if scaleY > 0.00001 then
|
||||
scaleY = scaleY * (((target.ascaleY - 1 + self.data.offsetScaleY) * scaleMix) + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local shearY = bone.ashearY
|
||||
if shearMix ~= 0 then shearY = shearY + (target.ashearY + self.data.offsetShearY) * shearMix end
|
||||
|
||||
local rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate
|
||||
local x = bone.ax + (target.ax + this.data.offsetX) * mixX
|
||||
local y = bone.ay + (target.ay + this.data.offsetY) * mixY
|
||||
local scaleX = (bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX) + 1)
|
||||
local scaleY = (bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY) + 1)
|
||||
local shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY
|
||||
bone:updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY)
|
||||
end
|
||||
end
|
||||
|
||||
@ -37,7 +37,7 @@ function TransformConstraintData.new (name)
|
||||
skinRequired = false,
|
||||
bones = {},
|
||||
target = nil,
|
||||
rotateMix = 0, translateMix = 0, scaleMix = 0, shearMix = 0,
|
||||
mixRotate = 0, mixX = 0, mixY = 0, mixScaleX = 0, mixScaleY = 0, mixShearY = 0,
|
||||
offsetRotation = 0, offsetX = 0, offsetY = 0, offsetScaleX = 0, offsetScaleY = 0, offsetShearY = 0,
|
||||
relative = false,
|
||||
local_ = false
|
||||
|
||||
@ -37,7 +37,6 @@ local AttachmentType = require "spine-lua.attachments.AttachmentType"
|
||||
local Attachment = require "spine-lua.attachments.Attachment"
|
||||
|
||||
local nextID = 0
|
||||
local SHL_11 = 2048
|
||||
|
||||
local VertexAttachment = {}
|
||||
VertexAttachment.__index = VertexAttachment
|
||||
@ -45,16 +44,16 @@ setmetatable(VertexAttachment, { __index = Attachment })
|
||||
|
||||
function VertexAttachment.new (name, attachmentType)
|
||||
local self = Attachment.new(name, attachmentType)
|
||||
self.vertexAttachment = true
|
||||
|
||||
self.id = nextID
|
||||
nextID = nextID + 1
|
||||
|
||||
self.isVertexAttachment = true
|
||||
self.bones = nil
|
||||
self.vertices = nil
|
||||
self.worldVerticesLength = 0
|
||||
while nextID > 65535 do
|
||||
nextID = nextID - 65535
|
||||
end
|
||||
self.id = nextID * SHL_11
|
||||
self.deformAttachment = self
|
||||
nextID = nextID + 1
|
||||
|
||||
setmetatable(self, VertexAttachment)
|
||||
return self
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user