[lua] Ported skin bones/constraints changes. See #1346.

This commit is contained in:
badlogic 2019-06-07 11:28:47 +02:00
parent d85e18c5f5
commit b113966ed4
15 changed files with 250 additions and 172 deletions

View File

@ -161,66 +161,70 @@ function spine.Skeleton:updateWorldTransform()
local uvs = nil
local numVertices = 0
local indices = nil
if attachment then
if attachment.type == spine.AttachmentType.region then
numVertices = 4
vertices = worldVertices
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
uvs = attachment.uvs
indices = QUAD_TRIANGLES
texture = attachment.region.renderObject.texture
blendMode = toCoronaBlendMode(slot.data.blendMode)
elseif attachment.type == spine.AttachmentType.mesh then
numVertices = attachment.worldVerticesLength / 2
vertices = worldVertices
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
uvs = attachment.uvs
indices = attachment.triangles
texture = attachment.region.renderObject.texture
blendMode = toCoronaBlendMode(slot.data.blendMode)
elseif attachment.type == spine.AttachmentType.clipping then
self.clipper:clipStart(slot, attachment)
end
if slot.bone.active then
if attachment then
if attachment.type == spine.AttachmentType.region then
numVertices = 4
vertices = worldVertices
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
uvs = attachment.uvs
indices = QUAD_TRIANGLES
texture = attachment.region.renderObject.texture
blendMode = toCoronaBlendMode(slot.data.blendMode)
elseif attachment.type == spine.AttachmentType.mesh then
numVertices = attachment.worldVerticesLength / 2
vertices = worldVertices
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
uvs = attachment.uvs
indices = attachment.triangles
texture = attachment.region.renderObject.texture
blendMode = toCoronaBlendMode(slot.data.blendMode)
elseif attachment.type == spine.AttachmentType.clipping then
self.clipper:clipStart(slot, attachment)
end
if texture and vertices and indices then
local skeleton = slot.bone.skeleton
local skeletonColor = skeleton.color
local slotColor = slot.color
local attachmentColor = attachment.color
local alpha = skeletonColor.a * slotColor.a * attachmentColor.a
local multiplier = alpha
if premultipliedAlpha then multiplier = 1 end
color:set(skeletonColor.r * slotColor.r * attachmentColor.r * multiplier,
skeletonColor.g * slotColor.g * attachmentColor.g * multiplier,
skeletonColor.b * slotColor.b * attachmentColor.b * multiplier,
alpha)
if not lastTexture then lastTexture = texture end
if lastColor.r == -1 then lastColor:setFrom(color) end
if not lastBlendMode then lastBlendMode = blendMode end
if texture and vertices and indices then
local skeleton = slot.bone.skeleton
local skeletonColor = skeleton.color
local slotColor = slot.color
local attachmentColor = attachment.color
local alpha = skeletonColor.a * slotColor.a * attachmentColor.a
local multiplier = alpha
if premultipliedAlpha then multiplier = 1 end
color:set(skeletonColor.r * slotColor.r * attachmentColor.r * multiplier,
skeletonColor.g * slotColor.g * attachmentColor.g * multiplier,
skeletonColor.b * slotColor.b * attachmentColor.b * multiplier,
alpha)
if not lastTexture then lastTexture = texture end
if lastColor.r == -1 then lastColor:setFrom(color) end
if not lastBlendMode then lastBlendMode = blendMode end
if (texture ~= lastTexture or not colorEquals(color, lastColor) or blendMode ~= lastBlendMode) then
self:flush(groupVertices, groupUvs, groupIndices, lastTexture, lastColor, lastBlendMode, drawingGroup)
lastTexture = texture
lastColor:setFrom(color)
lastBlendMode = blendMode
groupVertices = {}
groupUvs = {}
groupIndices = {}
end
if self.clipper:isClipping() then
self.clipper:clipTriangles(vertices, uvs, indices, #indices)
vertices = self.clipper.clippedVertices
numVertices = #vertices / 2
uvs = self.clipper.clippedUVs
indices = self.clipper.clippedTriangles
end
if (texture ~= lastTexture or not colorEquals(color, lastColor) or blendMode ~= lastBlendMode) then
self:flush(groupVertices, groupUvs, groupIndices, lastTexture, lastColor, lastBlendMode, drawingGroup)
lastTexture = texture
lastColor:setFrom(color)
lastBlendMode = blendMode
groupVertices = {}
groupUvs = {}
groupIndices = {}
end
if self.clipper:isClipping() then
self.clipper:clipTriangles(vertices, uvs, indices, #indices)
vertices = self.clipper.clippedVertices
numVertices = #vertices / 2
uvs = self.clipper.clippedUVs
indices = self.clipper.clippedTriangles
end
self:batch(vertices, uvs, numVertices, indices, groupVertices, groupUvs, groupIndices)
end
self.clipper:clipEnd(slot)
self:batch(vertices, uvs, numVertices, indices, groupVertices, groupUvs, groupIndices)
end
self.clipper:clipEnd(slot)
end
end
end

View File

@ -320,76 +320,78 @@ function SkeletonRenderer:draw (skeleton)
local drawOrder = skeleton.drawOrder
for i, slot in ipairs(drawOrder) do
local attachment = slot.attachment
local vertices = worldVertices
local uvs = nil
local indices = nil
local texture = nil
local color = tmpColor
if attachment then
if attachment.type == spine.AttachmentType.region then
numVertices = 4
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
uvs = attachment.uvs
indices = SkeletonRenderer.QUAD_TRIANGLES
texture = attachment.region.renderObject.texture
elseif attachment.type == spine.AttachmentType.mesh then
numVertices = attachment.worldVerticesLength / 2
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
uvs = attachment.uvs
indices = attachment.triangles
texture = attachment.region.renderObject.texture
elseif attachment.type == spine.AttachmentType.clipping then
self.clipper:clipStart(slot, attachment)
end
if slot.bone.active then
local attachment = slot.attachment
local vertices = worldVertices
local uvs = nil
local indices = nil
local texture = nil
local color = tmpColor
if attachment then
if attachment.type == spine.AttachmentType.region then
numVertices = 4
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
uvs = attachment.uvs
indices = SkeletonRenderer.QUAD_TRIANGLES
texture = attachment.region.renderObject.texture
elseif attachment.type == spine.AttachmentType.mesh then
numVertices = attachment.worldVerticesLength / 2
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
uvs = attachment.uvs
indices = attachment.triangles
texture = attachment.region.renderObject.texture
elseif attachment.type == spine.AttachmentType.clipping then
self.clipper:clipStart(slot, attachment)
end
if texture then
local slotBlendMode = slot.data.blendMode
if lastBlendMode ~= slotBlendMode then
batcher:stop()
batcher:begin()
if texture then
local slotBlendMode = slot.data.blendMode
if lastBlendMode ~= slotBlendMode then
batcher:stop()
batcher:begin()
if slotBlendMode == spine.BlendMode.normal then
love.graphics.setBlendMode("alpha")
elseif slotBlendMode == spine.BlendMode.additive then
love.graphics.setBlendMode("add")
elseif slotBlendMode == spine.BlendMode.multiply then
love.graphics.setBlendMode("multiply", "premultiplied")
elseif slotBlendMode == spine.BlendMode.screen then
love.graphics.setBlendMode("screen")
end
lastBlendMode = slotBlendMode
end
if slotBlendMode == spine.BlendMode.normal then
love.graphics.setBlendMode("alpha")
elseif slotBlendMode == spine.BlendMode.additive then
love.graphics.setBlendMode("add")
elseif slotBlendMode == spine.BlendMode.multiply then
love.graphics.setBlendMode("multiply", "premultiplied")
elseif slotBlendMode == spine.BlendMode.screen then
love.graphics.setBlendMode("screen")
end
lastBlendMode = slotBlendMode
end
local skeleton = slot.bone.skeleton
local skeletonColor = skeleton.color
local slotColor = slot.color
local attachmentColor = attachment.color
local alpha = skeletonColor.a * slotColor.a * attachmentColor.a
local multiplier = alpha
if premultipliedAlpha then multiplier = 1 end
color:set(skeletonColor.r * slotColor.r * attachmentColor.r * multiplier,
skeletonColor.g * slotColor.g * attachmentColor.g * multiplier,
skeletonColor.b * slotColor.b * attachmentColor.b * multiplier,
alpha)
local dark = tmpColor2
if slot.darkColor then dark = slot.darkColor
else dark:set(0, 0, 0, 0) end
if self.clipper:isClipping() then
self.clipper:clipTriangles(vertices, attachment.uvs, indices, #indices)
vertices = self.clipper.clippedVertices
numVertices = #vertices / 2
uvs = self.clipper.clippedUVs
indices = self.clipper.clippedTriangles
end
batcher:draw(texture, vertices, uvs, numVertices, indices, color, dark, self.vertexEffect)
end
self.clipper:clipEnd(slot)
end
local skeleton = slot.bone.skeleton
local skeletonColor = skeleton.color
local slotColor = slot.color
local attachmentColor = attachment.color
local alpha = skeletonColor.a * slotColor.a * attachmentColor.a
local multiplier = alpha
if premultipliedAlpha then multiplier = 1 end
color:set(skeletonColor.r * slotColor.r * attachmentColor.r * multiplier,
skeletonColor.g * slotColor.g * attachmentColor.g * multiplier,
skeletonColor.b * slotColor.b * attachmentColor.b * multiplier,
alpha)
local dark = tmpColor2
if slot.darkColor then dark = slot.darkColor
else dark:set(0, 0, 0, 0) end
if self.clipper:isClipping() then
self.clipper:clipTriangles(vertices, attachment.uvs, indices, #indices)
vertices = self.clipper.clippedVertices
numVertices = #vertices / 2
uvs = self.clipper.clippedUVs
indices = self.clipper.clippedTriangles
end
batcher:draw(texture, vertices, uvs, numVertices, indices, color, dark, self.vertexEffect)
end
self.clipper:clipEnd(slot)
end
end
end
batcher:stop()

View File

@ -259,6 +259,7 @@ function Animation.RotateTimeline.new (frameCount)
local frames = self.frames
local bone = skeleton.bones[self.boneIndex]
if not bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
bone.rotation = bone.data.rotation
@ -334,6 +335,8 @@ function Animation.TranslateTimeline.new (frameCount)
local frames = self.frames
local bone = skeleton.bones[self.boneIndex]
if not bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
bone.x = bone.data.x
@ -398,6 +401,8 @@ function Animation.ScaleTimeline.new (frameCount)
local frames = self.frames
local bone = skeleton.bones[self.boneIndex]
if not bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
bone.scaleX = bone.data.scaleX
@ -499,6 +504,8 @@ function Animation.ShearTimeline.new (frameCount)
local frames = self.frames
local bone = skeleton.bones[self.boneIndex]
if not bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
bone.shearX = bone.data.shearX
@ -577,6 +584,7 @@ function Animation.ColorTimeline.new (frameCount)
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames
local slot = skeleton.slots[self.slotIndex]
if not slot.bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
slot.color:setFrom(slot.data.color)
@ -668,6 +676,8 @@ function Animation.TwoColorTimeline.new (frameCount)
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames
local slot = skeleton.slots[self.slotIndex]
if not slot.bone.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
slot.color:setFrom(slot.data.color)
@ -758,6 +768,7 @@ function Animation.AttachmentTimeline.new (frameCount)
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local slot = skeleton.slots[self.slotIndex]
if not slot.bone.active then return end
local attachmentName
if direction == MixDirection.out and blend == MixBlend.setup then
attachmentName = slot.data.attachmentName
@ -820,6 +831,8 @@ function Animation.DeformTimeline.new (frameCount)
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local slot = skeleton.slots[self.slotIndex]
if not slot.bone.active then return end
local slotAttachment = slot.attachment
if not slotAttachment then return end
if not (slotAttachment.type == AttachmentType.mesh or slotAttachment.type == AttachmentType.linkedmesh or slotAttachment.type == AttachmentType.path or slotAttachment.type == AttachmentType.boundingbox) then return end
@ -1211,6 +1224,7 @@ function Animation.IkConstraintTimeline.new (frameCount)
local frames = self.frames
local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
if not constraint.active then return end
if time < frames[0] then
if blend == MixBlend.setup then
constraint.mix = constraint.data.mix
@ -1316,6 +1330,8 @@ function Animation.TransformConstraintTimeline.new (frameCount)
local frames = self.frames
local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
if not constraint.active then return end
if time < frames[0] then
local data = constraint.data
if blend == MixBlend.setup then
@ -1402,6 +1418,8 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if not constraint.active then return end
if (time < frames[0]) then
if blend == MixBlend.setup then
constraint.position = constraint.data.position
@ -1461,6 +1479,8 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if not constraint.active then return end
if (time < frames[0]) then
if blend == MixBlend.setup then
constraint.spacing = constraint.data.spacing
@ -1524,6 +1544,8 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if not constraint.active then return end
if (time < frames[0]) then
if blend == MixBlend.setup then
constraint.rotateMix = constraint.data.rotateMix

View File

@ -488,6 +488,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, bl
local rotateTimeline = timeline
local frames = rotateTimeline.frames
local bone = skeleton.bones[rotateTimeline.boneIndex]
if not bone.active then return end
local r1 = 0
local r2 = 0
if time < frames[0] then

View File

@ -69,7 +69,8 @@ function Bone.new (data, skeleton, parent)
a = 0, b = 0, worldX = 0, -- a b x
c = 0, d = 0, worldY = 0, -- c d y
sorted = false
sorted = false,
active = false
}
setmetatable(self, Bone)

View File

@ -46,7 +46,8 @@ function BoneData.new (index, name, parent)
scaleX = 1, scaleY = 1,
shearX = 0, shearY = 0,
inheritRotation = true,
inheritScale = true
inheritScale = true,
skinRequired = false
}
return self

View File

@ -54,6 +54,7 @@ function IkConstraint.new (data, skeleton)
compress = data.compress,
stretch = data.stretch,
bendDirection = data.bendDirection,
active = false
}
setmetatable(self, IkConstraint)

View File

@ -34,6 +34,7 @@ function IkConstraintData.new (name)
local self = {
name = name,
order = 0,
skinRequired = false,
bones = {},
target = nil,
bendDirection = 1,

View File

@ -73,7 +73,8 @@ function PathConstraint.new (data, skeleton)
world = {},
curves = {},
lengths = {},
segments = {}
segments = {},
active = false
}
setmetatable(self, PathConstraint)

View File

@ -34,6 +34,7 @@ function PathConstraintData.new (name)
local self = {
name = name,
order = 0,
skinRequired = false,
bones = {},
target = nil,
positionMode = nil,

View File

@ -113,8 +113,21 @@ function Skeleton:updateCache ()
local bones = self.bones
for _, bone in ipairs(bones) do
bone.sorted = false
bone.sorted = bone.data.skinRequired
bone.active = not bone.sorted
end
if self.skin then
local skinBones = self.skin.bones
for i, boneData in ipairs(skinBones) do
local bone = bones[boneData.index]
while bone do
bone.sorted = false
bone.active = true
bone = bone.parent
end
end
end
local ikConstraints = self.ikConstraints
local transformConstraints = self.transformConstraints
@ -172,6 +185,9 @@ function Skeleton:updateCache ()
end
function Skeleton:sortIkConstraint (constraint)
constraint.active = constraint.target.active and ((not constraint.data.skinRequired) or (self.skin and utils.arrayContains(self.skin.constraints, constraint)))
if not constraint.active then return end
local target = constraint.target
self:sortBone(target)
@ -198,6 +214,9 @@ function Skeleton:sortIkConstraint (constraint)
end
function Skeleton:sortPathConstraint(constraint)
constraint.active = constraint.target.bone.active and ((not constraint.data.skinRequired) or (self.skin and utils.arrayContains(self.skin.constraints, constraint)))
if not constraint.active then return end
local slot = constraint.target
local slotIndex = slot.data.index
local slotBone = slot.bone
@ -229,6 +248,9 @@ function Skeleton:sortPathConstraint(constraint)
end
function Skeleton:sortTransformConstraint(constraint)
constraint.active = constraint.target.active and ((not constraint.data.skinRequired) or (self.skin and utils.arrayContains(self.skin.constraints, constraint)))
if not constraint.active then return end
self:sortBone(constraint.target)
local constrained = constraint.bones
@ -301,8 +323,10 @@ end
function Skeleton:sortReset(bones)
for _, bone in ipairs(bones) do
if bone.sorted then self:sortReset(bone.children) end
bone.sorted = false
if bone.active then
if bone.sorted then self:sortReset(bone.children) end
bone.sorted = false
end
end
end
@ -412,6 +436,7 @@ function Skeleton:setSkin (skinName)
end
function Skeleton:setSkinByReference(newSkin)
if (self.skin == newSkin) then return end
if newSkin then
if self.skin then
newSkin:attachAll(self, self.skin)
@ -429,6 +454,7 @@ function Skeleton:setSkinByReference(newSkin)
end
end
self.skin = newSkin
self:updateCache()
end
function Skeleton:getAttachment (slotName, attachmentName)
@ -498,28 +524,30 @@ function Skeleton:getBounds(offset, size)
local maxX = -99999999
local maxY = -99999999
for _, slot in ipairs(drawOrder) do
local vertices = {}
local attachment = slot.attachment
if attachment then
if attachment.type == AttachmentType.region then
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
elseif attachment.type == AttachmentType.mesh then
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
end
end
if #vertices > 0 then
local nn = #vertices
local ii = 1
while ii <= nn do
local x = vertices[ii]
local y = vertices[ii + 1]
minX = math_min(minX, x)
minY = math_min(minY, y)
maxX = math_max(maxX, x)
maxY = math_max(maxY, y)
ii = ii + 2
end
end
if slot.bone.active then
local vertices = {}
local attachment = slot.attachment
if attachment then
if attachment.type == AttachmentType.region then
attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
elseif attachment.type == AttachmentType.mesh then
attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
end
end
if #vertices > 0 then
local nn = #vertices
local ii = 1
while ii <= nn do
local x = vertices[ii]
local y = vertices[ii + 1]
minX = math_min(minX, x)
minY = math_min(minY, y)
maxX = math_max(maxX, x)
maxY = math_max(maxY, y)
ii = ii + 2
end
end
end
end
offset[1] = minX
offset[2] = minY

View File

@ -111,6 +111,7 @@ function SkeletonJson.new (attachmentLoader)
data.shearX = getValue(boneMap, "shearX", 0);
data.shearY = getValue(boneMap, "shearY", 0);
data.transformMode = TransformMode[getValue(boneMap, "transform", "normal")]
data.skinRequired = getValue(boneMap, "skin", false)
table_insert(skeletonData.bones, data)
end
@ -154,6 +155,7 @@ function SkeletonJson.new (attachmentLoader)
for _,constraintMap in ipairs(root["ik"]) do
local data = IkConstraintData.new(constraintMap["name"])
data.order = getValue(constraintMap, "order", 0)
data.skinRequired = getValue(constraintMap, "skin", false)
for _,boneName in ipairs(constraintMap["bones"]) do
local bone = skeletonData:findBone(boneName)
@ -184,6 +186,7 @@ function SkeletonJson.new (attachmentLoader)
for _,constraintMap in ipairs(root["transform"]) do
local data = TransformConstraintData.new(constraintMap.name)
data.order = getValue(constraintMap, "order", 0)
data.skinRequired = getValue(constraintMap, "skin", false)
for _,boneName in ipairs(constraintMap.bones) do
local bone = skeletonData:findBone(boneName)
@ -216,6 +219,7 @@ function SkeletonJson.new (attachmentLoader)
for _,constraintMap in ipairs(root.path) do
local data = PathConstraintData.new(constraintMap.name);
data.order = getValue(constraintMap, "order", 0)
data.skinRequired = getValue(constraintMap, "skin", false)
for _,boneName in ipairs(constraintMap.bones) do
local bone = skeletonData:findBone(boneName)
@ -245,8 +249,8 @@ function SkeletonJson.new (attachmentLoader)
-- Skins.
if root["skins"] then
for skinName,skinMap in pairs(root["skins"]) do
local skin = Skin.new(skinName)
for slotName,slotMap in pairs(skinMap) do
local skin = Skin.new(skinMap["name"])
for slotName,slotMap in pairs(skinMap.attachments) do
local slotIndex = skeletonData.slotNameIndices[slotName]
for attachmentName,attachmentMap in pairs(slotMap) do
local attachment = readAttachment(attachmentMap, skin, slotIndex, attachmentName, skeletonData)
@ -511,7 +515,7 @@ function SkeletonJson.new (attachmentLoader)
for _,valueMap in ipairs(values) do
local color = valueMap["color"]
timeline:setFrame(
frameIndex, valueMap["time"],
frameIndex, getValue(valueMap, "time", 0),
tonumber(color:sub(1, 2), 16) / 255,
tonumber(color:sub(3, 4), 16) / 255,
tonumber(color:sub(5, 6), 16) / 255,
@ -531,7 +535,7 @@ function SkeletonJson.new (attachmentLoader)
local light = valueMap["light"]
local dark = valueMap["dark"]
timeline:setFrame(
frameIndex, valueMap["time"],
frameIndex, getValue(valueMap, "time", 0),
tonumber(light:sub(1, 2), 16) / 255,
tonumber(light:sub(3, 4), 16) / 255,
tonumber(light:sub(5, 6), 16) / 255,
@ -552,7 +556,7 @@ function SkeletonJson.new (attachmentLoader)
local frameIndex = 0
for _,valueMap in ipairs(values) do
local attachmentName = valueMap["name"]
timeline:setFrame(frameIndex, valueMap["time"], attachmentName)
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), attachmentName)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
@ -579,7 +583,7 @@ function SkeletonJson.new (attachmentLoader)
local frameIndex = 0
for _,valueMap in ipairs(values) do
timeline:setFrame(frameIndex, valueMap["time"], valueMap["angle"])
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "angle", 0))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -589,8 +593,10 @@ function SkeletonJson.new (attachmentLoader)
elseif timelineName == "translate" or timelineName == "scale" or timelineName == "shear" then
local timeline
local timelineScale = 1
local defaultValue = 0
if timelineName == "scale" then
timeline = Animation.ScaleTimeline.new(#values)
defaultValue = 1
elseif timelineName == "shear" then
timeline = Animation.ShearTimeline.new(#values)
else
@ -601,9 +607,9 @@ function SkeletonJson.new (attachmentLoader)
local frameIndex = 0
for _,valueMap in ipairs(values) do
local x = (valueMap["x"] or 0) * timelineScale
local y = (valueMap["y"] or 0) * timelineScale
timeline:setFrame(frameIndex, valueMap["time"], x, y)
local x = getValue(valueMap, "x", defaultValue) * timelineScale
local y = getValue(valueMap, "y", defaultValue) * timelineScale
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), x, y)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -638,7 +644,7 @@ function SkeletonJson.new (attachmentLoader)
if valueMap["stretch"] ~= nil then stretch = valueMap["stretch"] end
local compress = false
if valueMap["compress"] ~= nil then compress = valueMap["compress"] end
timeline:setFrame(frameIndex, valueMap["time"], mix, bendPositive, compress, stretch)
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), mix, bendPositive, compress, stretch)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -661,7 +667,7 @@ function SkeletonJson.new (attachmentLoader)
end
local frameIndex = 0
for _,valueMap in ipairs(values) do
timeline:setFrame(frameIndex, valueMap.time, getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1), getValue(valueMap, "scaleMix", 1), getValue(valueMap, "shearMix", 1))
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1), getValue(valueMap, "scaleMix", 1), getValue(valueMap, "shearMix", 1))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -690,7 +696,7 @@ function SkeletonJson.new (attachmentLoader)
timeline.pathConstraintIndex = index
local frameIndex = 0
for _,valueMap in ipairs(timelineMap) do
timeline:setFrame(frameIndex, valueMap.time, getValue(valueMap, timelineName, 0) * timelineScale)
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, timelineName, 0) * timelineScale)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -701,7 +707,7 @@ function SkeletonJson.new (attachmentLoader)
timeline.pathConstraintIndex = index
local frameIndex = 0
for _,valueMap in ipairs(timelineMap) do
timeline:setFrame(frameIndex, valueMap.time, getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1))
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1))
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -761,7 +767,7 @@ function SkeletonJson.new (attachmentLoader)
end
end
timeline:setFrame(frameIndex, valueMap.time, deform)
timeline:setFrame(frameIndex, getValue(valueMap, "time", 0), deform)
readCurve(valueMap, timeline, frameIndex)
frameIndex = frameIndex + 1
end
@ -814,7 +820,7 @@ function SkeletonJson.new (attachmentLoader)
end
end
end
timeline:setFrame(frameIndex, drawOrderMap["time"], drawOrder)
timeline:setFrame(frameIndex, getValue(drawOrderMap, "time", 0), drawOrder)
frameIndex = frameIndex + 1
end
table_insert(timelines, timeline)
@ -829,7 +835,7 @@ function SkeletonJson.new (attachmentLoader)
for _,eventMap in ipairs(events) do
local eventData = skeletonData:findEvent(eventMap["name"])
if not eventData then error("Event not found: " .. eventMap["name"]) end
local event = Event.new(eventMap["time"], eventData)
local event = Event.new(getValue(eventMap, "time", 0), eventData)
if eventMap["int"] ~= nil then
event.intValue = eventMap["int"]
else
@ -864,8 +870,8 @@ function SkeletonJson.new (attachmentLoader)
if not curve then return end
if curve == "stepped" then
timeline:setStepped(frameIndex)
elseif #curve > 0 then
timeline:setCurve(frameIndex, curve[1], curve[2], curve[3], curve[4])
else
timeline:setCurve(frameIndex, getValue(map, "curve", 0), getValue(map, "c2", 0), getValue(map, "c3", 1), getValue(map, "c4", 1))
end
end

View File

@ -54,7 +54,8 @@ function TransformConstraint.new (data, skeleton)
bones = {},
target = nil,
rotateMix = data.rotateMix, translateMix = data.translateMix, scaleMix = data.scaleMix, shearMix = data.shearMix,
temp = { 0, 0 }
temp = { 0, 0 },
active = false
}
setmetatable(self, TransformConstraint)

View File

@ -34,6 +34,7 @@ function TransformConstraintData.new (name)
local self = {
name = name,
order = 0,
skinRequired = false,
bones = {},
target = nil,
rotateMix = 0, translateMix = 0, scaleMix = 0, shearMix = 0,

View File

@ -129,6 +129,13 @@ function utils.arrayCopy (src, srcOffset, dst, dstOffset, size)
end
end
function utils.arrayContains(array, element)
for i, arrayElement in ipairs(array) do
if arrayElement == element then return true end
end
return false
end
function utils.clamp (value, min, max)
if value < min then return min end
if value > max then return max end