mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-19 00:06:42 +08:00
[lua] Ported skin bones/constraints changes. See #1346.
This commit is contained in:
parent
d85e18c5f5
commit
b113966ed4
@ -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
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -54,6 +54,7 @@ function IkConstraint.new (data, skeleton)
|
||||
compress = data.compress,
|
||||
stretch = data.stretch,
|
||||
bendDirection = data.bendDirection,
|
||||
active = false
|
||||
}
|
||||
setmetatable(self, IkConstraint)
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ function IkConstraintData.new (name)
|
||||
local self = {
|
||||
name = name,
|
||||
order = 0,
|
||||
skinRequired = false,
|
||||
bones = {},
|
||||
target = nil,
|
||||
bendDirection = 1,
|
||||
|
||||
@ -73,7 +73,8 @@ function PathConstraint.new (data, skeleton)
|
||||
world = {},
|
||||
curves = {},
|
||||
lengths = {},
|
||||
segments = {}
|
||||
segments = {},
|
||||
active = false
|
||||
}
|
||||
setmetatable(self, PathConstraint)
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ function PathConstraintData.new (name)
|
||||
local self = {
|
||||
name = name,
|
||||
order = 0,
|
||||
skinRequired = false,
|
||||
bones = {},
|
||||
target = nil,
|
||||
positionMode = nil,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user