Jelajahi Sumber

[lua] First pass on 3.5 update, only Skeleton:updateCache and updateWorldTransform missing

badlogic 9 tahun lalu
induk
melakukan
7cd0cd5fde

+ 114 - 113
spine-lua/Bone.lua

@@ -36,6 +36,8 @@ local math_cos = math.cos
 local math_atan2 = math.atan2
 local math_atan2 = math.atan2
 local math_sqrt = math.sqrt
 local math_sqrt = math.sqrt
 
 
+local TransformMode = require "spine-lua.TransformMode"
+
 function math.sign(x)
 function math.sign(x)
 	if x<0 then
 	if x<0 then
 		return -1
 		return -1
@@ -61,11 +63,11 @@ function Bone.new (data, skeleton, parent)
 		parent = parent,
 		parent = parent,
 		children = { },
 		children = { },
 		x = 0, y = 0, rotation = 0, scaleX = 1, scaleY = 1, shearX = 0, shearY = 0,
 		x = 0, y = 0, rotation = 0, scaleX = 1, scaleY = 1, shearX = 0, shearY = 0,
-		appliedRotation = 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
 		a = 0, b = 0, worldX = 0, -- a b x
 		c = 0, d = 0, worldY = 0, -- c d y
 		c = 0, d = 0, worldY = 0, -- c d y
-		worldSignX = 0, worldSignY = 0,
 		sorted = false
 		sorted = false
 	}
 	}
 	setmetatable(self, Bone)
 	setmetatable(self, Bone)
@@ -83,18 +85,24 @@ function Bone:updateWorldTransform ()
 end
 end
 
 
 function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX, shearY)
 function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX, shearY)
-	self.appliedRotation = rotation
-
-	local rotationY = rotation + 90 + shearY
-	local rotationRad = math_rad(rotation + shearX)
-	local rotationYRad = math_rad(rotationY)
-	local la = math_cos(rotationRad) * scaleX
-	local lb = math_cos(rotationYRad) * scaleY
-	local lc = math_sin(rotationRad) * scaleX
-	local ld = math_sin(rotationYRad) * scaleY
+	self.ax = x
+	self.ay = y
+	self.arotation = rotation
+	self.ascaleX = scaleX
+	self.ascaleY = scaleY
+	self.ashearX = shearX
+	self.ashearY = shearY
+	self.appliedValid = true
 
 
 	local parent = self.parent
 	local parent = self.parent
 	if parent == nil then
 	if parent == nil then
+		local rotationY = rotation + 90 + shearY
+		local rotationRad = math_rad(rotation + shearX)
+		local rotationYRad = math_rad(rotationY)
+		local la = math_cos(rotationRad) * scaleX
+		local lb = math_cos(rotationYRad) * scaleY
+		local lc = math_sin(rotationRad) * scaleX
+		local ld = math_sin(rotationYRad) * scaleY
 		local skeleton = self.skeleton
 		local skeleton = self.skeleton
 		if skeleton.flipX then
 		if skeleton.flipX then
 			x = -x
 			x = -x
@@ -110,10 +118,8 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
 		self.b = lb
 		self.b = lb
 		self.c = lc
 		self.c = lc
 		self.d = ld
 		self.d = ld
-		self.worldX = x
-		self.worldY = y
-		self.worldSignX = math_sign(scaleX)
-		self.worldSignY = math_sign(scaleY)
+		self.worldX = x + skeleton.x
+		self.worldY = y + skeleton.y
 		return
 		return
 	end
 	end
 
 
@@ -123,89 +129,85 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
 	local pd = parent.d
 	local pd = parent.d
 	self.worldX = pa * x + pb * y + parent.worldX
 	self.worldX = pa * x + pb * y + parent.worldX
 	self.worldY = pc * x + pd * y + parent.worldY
 	self.worldY = pc * x + pd * y + parent.worldY
-	self.worldSignX = parent.worldSignX * math_sign(scaleX)
-	self.worldSignY = parent.worldSignY * math_sign(scaleY)
 
 
-	if self.data.inheritRotation and self.data.inheritScale then
+	local transformMode = self.data.transformMode
+	if transformMode == TransformMode.normal then
+		local rotationY = rotation + 90 + shearY
+		local la = math_cos(math_rad(rotation + shearX)) * scaleX
+		local lb = math_cos(math_rad(rotationY)) * scaleY
+		local lc = math_sin(math_rad(rotation + shearX)) * scaleX
+		local ld = math_sin(math_rad(rotationY)) * scaleY
 		self.a = pa * la + pb * lc
 		self.a = pa * la + pb * lc
 		self.b = pa * lb + pb * ld
 		self.b = pa * lb + pb * ld
 		self.c = pc * la + pd * lc
 		self.c = pc * la + pd * lc
 		self.d = pc * lb + pd * ld
 		self.d = pc * lb + pd * ld
-	else
-		if self.data.inheritRotation then
-			pa = 1
-			pb = 0
-			pc = 0
-			pd = 1
-			repeat
-				local appliedRotationRad = math_rad(parent.appliedRotation)
-				local cos = math_cos(appliedRotationRad)
-				local sin = math_sin(appliedRotationRad)
-				local temp = pa * cos + pb * sin
-				pb = pb * cos - pa * sin
-				pa = temp
-				temp = pc * cos + pd * sin
-				pd = pd * cos - pc * sin
-				pc = temp
-
-				if not parent.data.inheritRotation then break end
-				parent = parent.parent
-			until parent == nil
-			self.a = pa * la + pb * lc
-			self.b = pa * lb + pb * ld
-			self.c = pc * la + pd * lc
-			self.d = pc * lb + pd * ld
-		elseif self.data.inheritScale then
-			pa = 1
-			pb = 0
-			pc = 0
-			pd = 1
-			repeat
-				local appliedRotationRad = math_rad(parent.appliedRotation)
-				local cos = math_cos(appliedRotationRad)
-				local sin = math_sin(appliedRotationRad)
-				local psx = parent.scaleX
-				local psy = parent.scaleY
-				local za = cos * psx
-				local zb = sin * psy
-				local zc = sin * psx
-				local zd = cos * psy
-				local temp = pa * za + pb * zc
-				pb = pb * zd - pa * zb
-				pa = temp
-				temp = pc * za + pd * zc
-				pd = pd * zd - pc * zb
-				pc = temp
-
-				if psx >= 0 then sin = -sin end
-				temp = pa * cos + pb * sin
-				pb = pb * cos - pa * sin
-				pa = temp
-				temp = pc * cos + pd * sin
-				pd = pd * cos - pc * sin
-				pc = temp
-
-				if not parent.data.inheritScale then break end
-				parent = parent.parent
-			until parent == nil
-			self.a = pa * la + pb * lc
-			self.b = pa * lb + pb * ld
-			self.c = pc * la + pd * lc
-			self.d = pc * lb + pd * ld
+		return;
+	elseif transformMode == TransformMode.onlyTranslation then
+		local rotationY = rotation + 90 + shearY
+		self.a = math_cos(math_rad(rotation + shearX)) * scaleX
+		self.b = math_cos(math_rad(rotationY)) * scaleY
+		self.c = math_sin(math_rad(rotation + shearX)) * scaleX
+		self.d = math_sin(math_rad(rotationY)) * scaleY
+	elseif transformMode == TransformMode.noRotationOrReflection then
+		local s = pa * pa + pc * pc
+		local prx = 0
+		if s > 0.0001 then
+			s = math_abs(pa * pd - pb * pc) / s
+			pb = pc * s
+			pd = pa * s
+			prx = math_deg(math_atan2(pc, pa));
 		else
 		else
-			self.a = la
-			self.b = lb
-			self.c = lc
-			self.d = ld
+			pa = 0;
+			pc = 0;
+			prx = 90 - math_deg(math_atan2(pd, pb));
 		end
 		end
-		if self.skeleton.flipX then
-			self.a = -self.a
+		local rx = rotation + shearX - prx
+		local ry = rotation + shearY - prx + 90
+		local la = math_cos(math_rad(rx)) * scaleX
+		local lb = math_cos(math_rad(ry)) * scaleY
+		local lc = math_sin(math_rad(rx)) * scaleX
+		local ld = math_sin(math_rad(ry)) * scaleY
+		a = pa * la - pb * lc
+		b = pa * lb - pb * ld
+		c = pc * la + pd * lc
+		d = pc * lb + pd * ld	
+	elseif transformMode == TransformMode.noScale or transformMode == TransformMode.noScaleOrReflection then
+		local cos = math_cos(math_rad(rotation))
+		local sin = math_sin(math_rad(rotation))
+		local za = pa * cos + pb * sin
+		local zc = pc * cos + pd * sin
+		local s = math_sqrt(za * za + zc * zc)
+		if s > 0.00001 then s = 1 / s end
+		za = za * s
+		zc = zc * s
+		s = math_sqrt(za * za + zc * zc)
+		local r = math_pi / 2 + math_atan2(zc, za)
+		local zb = math_cos(r) * s
+		local zd = math_sin(r) * s
+		local la = math_cos(math_rad(shearX)) * scaleX;
+		local lb = math_cos(math_rad(90 + shearY)) * scaleY;
+		local lc = math_sin(math_rad(shearX)) * scaleX;
+		local ld = math_sin(90 + shearY) * scaleY;
+		self.a = za * la + zb * lc
+		self.b = za * lb + zb * ld
+		self.c = zc * la + zd * lc
+		self.d = zc * lb + zd * ld
+		local flip = skeleton.flipX ~= skeleton.flipY
+		if transformMode ~= TransformMode.noScaleOrReflection then flip = pa * pd - pb * pc < 0 end
+		if flip then
 			self.b = -self.b
 			self.b = -self.b
-		end
-		if self.skeleton.flipY then
-			self.c = -self.c
 			self.d = -self.d
 			self.d = -self.d
 		end
 		end
+		return
+	end
+	
+	if skeleton.flipX then
+		self.a = -self.a
+		self.b = -self.b
+	end
+	if skeleton.flipY then
+		self.c = -self.c
+		self.d = -self.d
 	end
 	end
 end
 end
 
 
@@ -229,16 +231,16 @@ function Bone:getWorldRotationY ()
 end
 end
 
 
 function Bone:getWorldScaleX ()
 function Bone:getWorldScaleX ()
-	return math_sqrt(self.a * self.a + self.b * self.b) * self.worldSignX
+	return math_sqrt(self.a * self.a + self.c * self.c)
 end
 end
 
 
 function Bone:getWorldScaleY ()
 function Bone:getWorldScaleY ()
-	return math_sqrt(self.c * self.c + self.d * self.d) * self.worldSignY
+	return math_sqrt(self.b * self.b + self.d * self.d)
 end
 end
 
 
 function Bone:worldToLocalRotationX ()
 function Bone:worldToLocalRotationX ()
 	local parent = self.parent
 	local parent = self.parent
-	if parent == nil then return self.rotation end
+	if parent == nil then return self.arotation end
 	local pa = parent.a
 	local pa = parent.a
 	local pb = parent.b
 	local pb = parent.b
 	local pc = parent.c
 	local pc = parent.c
@@ -272,19 +274,19 @@ function Bone:rotateWorld (degrees)
 	self.b = cos * b - sin * d
 	self.b = cos * b - sin * d
 	self.c = sin * a + cos * c
 	self.c = sin * a + cos * c
 	self.d = sin * b + cos * d
 	self.d = sin * b + cos * d
+	self.appliedValid = false
 end
 end
 
 
-function updateLocalTransform ()
+function updateAppliedTransform ()
 	local parent = self.parent
 	local parent = self.parent
 	if parent == nil then
 	if parent == nil then
-		self.x = self.worldX
-		self.y = self.worldY
-		self.rotation = math_deg(math_atan2(self.c, self.a))
-		self.scaleX = math_sqrt(self.a * self.a + self.c * self.c)
-		self.scaleY = math_sqrt(self.b * self.b + self.d * self.d)
-		local det = self.a * self.d - self.b * self.c
-		self.shearX = 0
-		self.shearY = math_deg(math_atan2(self.a * self.b + self.c * self.d, det))
+		self.ax = self.worldX
+		self.ay = self.worldY
+		self.arotation = math_deg(math_atan2(self.c, self.a))
+		self.ascaleX = math_sqrt(self.a * self.a + self.c * self.c)
+		self.ascaleY = math_sqrt(self.b * self.b + self.d * self.d)
+		self.ashearX = 0
+		self.ashearY = math_deg(math_atan2(self.a * self.b + self.c * self.d, self.a * self.d - self.b * self.c))
 		return
 		return
 	end
 	end
 	local pa = parent.a
 	local pa = parent.a
@@ -294,8 +296,8 @@ function updateLocalTransform ()
 	local pid = 1 / (pa * pd - pb * pc)
 	local pid = 1 / (pa * pd - pb * pc)
 	local dx = self.worldX - parent.worldX
 	local dx = self.worldX - parent.worldX
 	local dy = self.worldY - parent.worldY
 	local dy = self.worldY - parent.worldY
-	self.x = (dx * pd * pid - dy * pb * pid)
-	self.y = (dy * pa * pid - dx * pc * pid)
+	self.ax = (dx * pd * pid - dy * pb * pid)
+	self.ay = (dy * pa * pid - dx * pc * pid)
 	local ia = pid * pd
 	local ia = pid * pd
 	local id = pid * pa
 	local id = pid * pa
 	local ib = pid * pb
 	local ib = pid * pb
@@ -304,20 +306,19 @@ function updateLocalTransform ()
 	local rb = ia * self.b - ib * self.d
 	local rb = ia * self.b - ib * self.d
 	local rc = id * self.c - ic * self.a
 	local rc = id * self.c - ic * self.a
 	local rd = id * self.d - ic * self.b
 	local rd = id * self.d - ic * self.b
-	self.shearX = 0
-	self.scaleX = math_sqrt(ra * ra + rc * rc)
-	if self.scaleX > 0.0001 then
+	self.ashearX = 0
+	self.ascaleX = math_sqrt(ra * ra + rc * rc)
+	if self.ascaleX > 0.0001 then
 		local det = ra * rd - rb * rc
 		local det = ra * rd - rb * rc
-		self.scaleY = det / self.scaleX
-		self.shearY = math_deg(math_atan2(ra * rb + rc * rd, det))
-		self.rotation = math_deg(math_atan2(rc, ra))
+		self.ascaleY = det / self.ascaleX
+		self.ashearY = math_deg(math_atan2(ra * rb + rc * rd, det))
+		self.arotation = math_deg(math_atan2(rc, ra))
 	else
 	else
-		self.scaleX = 0
-		self.scaleY = math_sqrt(rb * rb + rd * rd)
-		self.shearY = 0
-		self.rotation = 90 - math_deg(math_atan2(rd, rb))
+		self.ascaleX = 0
+		self.ascaleY = math_sqrt(rb * rb + rd * rd)
+		self.ashearY = 0
+		self.arotation = 90 - math_deg(math_atan2(rd, rb))
 	end
 	end
-	self.appliedRotation = self.rotation
 end
 end
 
 
 function Bone:worldToLocal (world)
 function Bone:worldToLocal (world)

+ 4 - 0
spine-lua/BoneData.lua

@@ -28,6 +28,9 @@
 -- POSSIBILITY OF SUCH DAMAGE.
 -- POSSIBILITY OF SUCH DAMAGE.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
+local setmetatable = setmetatable
+local TransformMode = require "spine-lua.TransformMode"
+
 local BoneData = {}
 local BoneData = {}
 function BoneData.new (index, name, parent)
 function BoneData.new (index, name, parent)
 	if index < 0 then error("index must be >= 0", 2) end
 	if index < 0 then error("index must be >= 0", 2) end
@@ -36,6 +39,7 @@ function BoneData.new (index, name, parent)
 	local self = {
 	local self = {
 		index = index,
 		index = index,
 		name = name,
 		name = name,
+		transformMode = TransformMode.normal,
 		parent = parent,
 		parent = parent,
 		length = 0,
 		length = 0,
 		x = 0, y = 0,
 		x = 0, y = 0,

+ 23 - 21
spine-lua/IkConstraint.lua

@@ -53,7 +53,6 @@ function IkConstraint.new (data, skeleton)
 		target = nil,
 		target = nil,
 		mix = data.mix,
 		mix = data.mix,
 		bendDirection = data.bendDirection,
 		bendDirection = data.bendDirection,
-		level = 0
 	}
 	}
 	setmetatable(self, IkConstraint)
 	setmetatable(self, IkConstraint)
 
 
@@ -82,20 +81,21 @@ function IkConstraint:update ()
 end
 end
 
 
 function IkConstraint:apply1 (bone, targetX, targetY, alpha)
 function IkConstraint:apply1 (bone, targetX, targetY, alpha)
-	local pp = bone.parent
-	local id = 1 / (pp.a * pp.d - pp.b * pp.c)
-	local x = targetX - pp.worldX
-	local y = targetY - pp.worldY
-	local tx = (x * pp.d - y * pp.b) * id - bone.x
-	local ty = (y * pp.a - x * pp.c) * id - bone.y
-	local rotationIK = math_deg(math_atan2(ty, tx)) - bone.shearX - bone.rotation
-	if bone.scaleX < 0 then rotationIK = rotationIK + 180 end
+	if not bone.appliedValid then bone:updateAppliedTransform() end
+	local p = bone.parent
+	local id = 1 / (p.a * p.d - p.b * p.c)
+	local x = targetX - p.worldX
+	local y = targetY - p.worldY
+	local tx = (x * p.d - y * p.b) * id - bone.ax
+	local ty = (y * p.a - x * p.c) * id - bone.ay
+	local rotationIK = math_deg(math_atan2(ty, tx)) - bone.ashearX - bone.arotation
+	if bone.ascaleX < 0 then rotationIK = rotationIK + 180 end
 	if rotationIK > 180 then
 	if rotationIK > 180 then
 		rotationIK = rotationIK - 360
 		rotationIK = rotationIK - 360
 	elseif (rotationIK < -180) then
 	elseif (rotationIK < -180) then
 		rotationIK = rotationIK + 360
 		rotationIK = rotationIK + 360
 	end
 	end
-	bone:updateWorldTransformWith(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX, bone.shearY)
+	bone:updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY)
 end
 end
 
 
 function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
 function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
@@ -103,11 +103,13 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
 		child:updateWorldTransform()
 		child:updateWorldTransform()
 		return
 		return
 	end
 	end
-	local px = parent.x
-	local py = parent.y
-	local psx = parent.scaleX
-	local psy = parent.scaleY
-	local csx = child.scaleX
+	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
+	local psy = parent.ascaleY
+	local csx = child.ascaleX
 	local os1 = 0
 	local os1 = 0
 	local os2 = 0
 	local os2 = 0
 	local s2 = 0
 	local s2 = 0
@@ -129,7 +131,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
 	else
 	else
 		os2 = 0
 		os2 = 0
 	end
 	end
-	local cx = child.x
+	local cx = child.ax
 	local cy = 0
 	local cy = 0
 	local cwx = 0
 	local cwx = 0
 	local cwy = 0
 	local cwy = 0
@@ -143,7 +145,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
 		cwx = a * cx + parent.worldX
 		cwx = a * cx + parent.worldX
 		cwy = c * cx + parent.worldY
 		cwy = c * cx + parent.worldY
 	else
 	else
-		cy = child.y
+		cy = child.ay
 		cwx = a * cx + b * cy + parent.worldX
 		cwx = a * cx + b * cy + parent.worldX
 		cwy = c * cx + d * cy + parent.worldY
 		cwy = c * cx + d * cy + parent.worldY
 	end
 	end
@@ -254,22 +256,22 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
 		end
 		end
 	end
 	end
 	local os = math_atan2(cy, cx) * s2
 	local os = math_atan2(cy, cx) * s2
-	local rotation = parent.rotation
+	local rotation = parent.arotation
 	a1 = math_deg(a1 - os) + os1 - rotation
 	a1 = math_deg(a1 - os) + os1 - rotation
 	if a1 > 180 then
 	if a1 > 180 then
 		a1 = a1 - 360
 		a1 = a1 - 360
 	elseif a1 < -180 then
 	elseif a1 < -180 then
 		a1 = a1 + 360
 		a1 = a1 + 360
 	end
 	end
-	parent:updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0)
+	parent:updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0)
 	rotation = child.rotation
 	rotation = child.rotation
-	a2 = (math_deg(a2 + os) - child.shearX) * s2 + os2 - rotation
+	a2 = (math_deg(a2 + os) - child.ashearX) * s2 + os2 - rotation
 	if a2 > 180 then
 	if a2 > 180 then
 		a2 = a2 - 360
 		a2 = a2 - 360
 	elseif a2 < -180 then
 	elseif a2 < -180 then
 		a2 = a2 + 360
 		a2 = a2 + 360
 	end
 	end
-	child:updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY);
+	child:updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
 end
 end
 
 
 return IkConstraint
 return IkConstraint

+ 1 - 0
spine-lua/IkConstraintData.lua

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

+ 4 - 6
spine-lua/PathConstraint.lua

@@ -134,9 +134,6 @@ function PathConstraint:update ()
 	end
 	end
 
 
 	local positions = self:computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PathConstraintData.PositionMode.percent, spacingMode == PathConstraintData.SpacingMode.percent)
 	local positions = self:computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PathConstraintData.PositionMode.percent, spacingMode == PathConstraintData.SpacingMode.percent)
-	local skeleton = self.target.bone.skeleton
-	local skeletonX = skeleton.x
-	local skeletonY = skeleton.y
 	local boneX = positions[1]
 	local boneX = positions[1]
 	local boneY = positions[2]
 	local boneY = positions[2]
 	local offsetRotation = data.offsetRotation
 	local offsetRotation = data.offsetRotation
@@ -145,8 +142,8 @@ function PathConstraint:update ()
 	local p = 3
 	local p = 3
 	while i < boneCount do
 	while i < boneCount do
 		local bone = bones[i + 1]
 		local bone = bones[i + 1]
-		bone.worldX = bone.worldX + (boneX - skeletonX - bone.worldX) * translateMix
-		bone.worldY = bone.worldY + (boneY - skeletonY - bone.worldY) * translateMix
+		bone.worldX = bone.worldX + (boneX - bone.worldX) * translateMix
+		bone.worldY = bone.worldY + (boneY - bone.worldY) * translateMix
 		local x = positions[p + 1]
 		local x = positions[p + 1]
 		local y = positions[p + 2]
 		local y = positions[p + 2]
 		local dx = x - boneX
 		local dx = x - boneX
@@ -197,6 +194,7 @@ function PathConstraint:update ()
 			bone.c = sin * a + cos * c
 			bone.c = sin * a + cos * c
 			bone.d = sin * b + cos * d
 			bone.d = sin * b + cos * d
 		end
 		end
+		bone.appliedValid = false
 		i = i + 1
 		i = i + 1
 		p = p + 3
 		p = p + 3
 	end
 	end
@@ -496,7 +494,7 @@ function PathConstraint:addAfterPosition(p, temp, i, out, o)
 end
 end
 
 
 function PathConstraint:addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents)
 function PathConstraint:addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents)
-	if p == 0 then p = 0.0001 end
+	if p == 0 or (p ~= p) then p = 0.0001 end
 	local tt = p * p
 	local tt = p * p
 	local ttt = tt * p
 	local ttt = tt * p
 	local u = 1 - p
 	local u = 1 - p

+ 1 - 0
spine-lua/PathConstraintData.lua

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

+ 2 - 1
spine-lua/Skeleton.lua

@@ -53,10 +53,11 @@ function Skeleton.new (data)
 		slots = {},
 		slots = {},
 		slotsByName = {},
 		slotsByName = {},
 		drawOrder = {},
 		drawOrder = {},
-		ikConstraints = {}, ikConstaintsSorted = {},
+		ikConstraints = {},
 		transformConstraints = {},
 		transformConstraints = {},
 		pathConstraints = {},
 		pathConstraints = {},
 		_updateCache = {},
 		_updateCache = {},
+		updateCacheReset = {},
 		skin = nil,
 		skin = nil,
 		color = Color.newWith(1, 1, 1, 1),
 		color = Color.newWith(1, 1, 1, 1),
 		time = 0,
 		time = 0,

+ 7 - 3
spine-lua/SkeletonJson.lua

@@ -45,6 +45,7 @@ local EventData = require "spine-lua.EventData"
 local Event = require "spine-lua.Event"
 local Event = require "spine-lua.Event"
 local AttachmentType = require "spine-lua.attachments.AttachmentType"
 local AttachmentType = require "spine-lua.attachments.AttachmentType"
 local BlendMode = require "spine-lua.BlendMode"
 local BlendMode = require "spine-lua.BlendMode"
+local TransformMode = require "spine-lua.TransformMode"
 local utils = require "spine-lua.utils"
 local utils = require "spine-lua.utils"
 
 
 local SkeletonJson = {}
 local SkeletonJson = {}
@@ -84,6 +85,7 @@ function SkeletonJson.new (attachmentLoader)
 			skeletonData.version = skeletonMap["spine"]
 			skeletonData.version = skeletonMap["spine"]
 			skeletonData.width = skeletonMap["width"]
 			skeletonData.width = skeletonMap["width"]
 			skeletonData.height = skeletonMap["height"]
 			skeletonData.height = skeletonMap["height"]
+			skeletonData.fps = skeletonMap["fps"]
 			skeletonData.imagesPath = skeletonMap["images"]
 			skeletonData.imagesPath = skeletonMap["images"]
 		end
 		end
 
 
@@ -106,8 +108,7 @@ function SkeletonJson.new (attachmentLoader)
 			data.scaleY = getValue(boneMap, "scaleY", 1);
 			data.scaleY = getValue(boneMap, "scaleY", 1);
 			data.shearX = getValue(boneMap, "shearX", 0);
 			data.shearX = getValue(boneMap, "shearX", 0);
 			data.shearY = getValue(boneMap, "shearY", 0);
 			data.shearY = getValue(boneMap, "shearY", 0);
-			data.inheritRotation = getValue(boneMap, "inheritRotation", true);
-			data.inheritScale = getValue(boneMap, "inheritScale", true);
+			data.transformMode = TransformMode[getValue(boneMap, "transform", "normal")]
 
 
 			table_insert(skeletonData.bones, data)
 			table_insert(skeletonData.bones, data)
 		end
 		end
@@ -142,6 +143,7 @@ function SkeletonJson.new (attachmentLoader)
 		if root["ik"] then
 		if root["ik"] then
 			for i,constraintMap in ipairs(root["ik"]) do
 			for i,constraintMap in ipairs(root["ik"]) do
 				local data = IkConstraintData.new(constraintMap["name"])
 				local data = IkConstraintData.new(constraintMap["name"])
+				data.order = getValue(constraintMap, "order", 0)
 
 
 				for i,boneName in ipairs(constraintMap["bones"]) do
 				for i,boneName in ipairs(constraintMap["bones"]) do
 					local bone = skeletonData:findBone(boneName)
 					local bone = skeletonData:findBone(boneName)
@@ -164,6 +166,7 @@ function SkeletonJson.new (attachmentLoader)
 		if root["transform"] then
 		if root["transform"] then
 			for i,constraintMap in ipairs(root["transform"]) do
 			for i,constraintMap in ipairs(root["transform"]) do
 				data = TransformConstraintData.new(constraintMap.name)
 				data = TransformConstraintData.new(constraintMap.name)
+				data.order = getValue(constraintMap, "order", 0)
 
 
 				for i,boneName in ipairs(constraintMap.bones) do
 				for i,boneName in ipairs(constraintMap.bones) do
 					local bone = skeletonData:findBone(boneName)
 					local bone = skeletonData:findBone(boneName)
@@ -195,6 +198,7 @@ function SkeletonJson.new (attachmentLoader)
 		if root["path"] then
 		if root["path"] then
 			for i,constraintMap in ipairs(root.path) do
 			for i,constraintMap in ipairs(root.path) do
 				local data = PathConstraintData.new(constraintMap.name);
 				local data = PathConstraintData.new(constraintMap.name);
+				data.order = getValue(constraintMap, "order", 0)
 
 
 				for i,boneName in ipairs(constraintMap.bones) do
 				for i,boneName in ipairs(constraintMap.bones) do
 					local bone = skeletonData:findBone(boneName)
 					local bone = skeletonData:findBone(boneName)
@@ -563,7 +567,7 @@ function SkeletonJson.new (attachmentLoader)
 				end
 				end
 				local frameIndex = 0
 				local frameIndex = 0
 				for i,valueMap in ipairs(values) do
 				for i,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, valueMap.time, getValue(valueMap, "rotateMix", 1), getValue(valueMap, "translateMix", 1), getValue(valueMap, "scaleMix", 1), getValue(valueMap, "shearMix", 1))
 					readCurve(valueMap, timeline, frameIndex)
 					readCurve(valueMap, timeline, frameIndex)
 					frameIndex = frameIndex + 1
 					frameIndex = frameIndex + 1
 				end
 				end

+ 9 - 2
spine-lua/TransformConstraint.lua

@@ -81,7 +81,8 @@ function TransformConstraint:update ()
 	local td = target.d
 	local td = target.d
 	local bones = self.bones
 	local bones = self.bones
 	for i, bone in ipairs(bones) do
 	for i, bone in ipairs(bones) do
-		if rotateMix > 0 then
+		local modified = false
+		if rotateMix ~= 0 then
 			local a = bone.a
 			local a = bone.a
 			local b = bone.b
 			local b = bone.b
 			local c = bone.c
 			local c = bone.c
@@ -99,15 +100,17 @@ function TransformConstraint:update ()
 			bone.b = cos * b - sin * d
 			bone.b = cos * b - sin * d
 			bone.c = sin * a + cos * c
 			bone.c = sin * a + cos * c
 			bone.d = sin * b + cos * d
 			bone.d = sin * b + cos * d
+			modified = true
 		end
 		end
 
 
-		if translateMix > 0 then
+		if translateMix ~= 0 then
 			local temp = self.temp
 			local temp = self.temp
 			temp[1] = self.data.offsetX
 			temp[1] = self.data.offsetX
 			temp[2] = self.data.offsetY
 			temp[2] = self.data.offsetY
 			target:localToWorld(temp)
 			target:localToWorld(temp)
 			bone.worldX = bone.worldX + (temp[1] - bone.worldX) * translateMix
 			bone.worldX = bone.worldX + (temp[1] - bone.worldX) * translateMix
 			bone.worldY = bone.worldY + (temp[2] - bone.worldY) * translateMix
 			bone.worldY = bone.worldY + (temp[2] - bone.worldY) * translateMix
+			modified = true
 		end
 		end
 
 
 		if scaleMix > 0 then
 		if scaleMix > 0 then
@@ -127,6 +130,7 @@ function TransformConstraint:update ()
 			end
 			end
 			bone.b = bone.b * s
 			bone.b = bone.b * s
 			bone.d = bone.d * s
 			bone.d = bone.d * s
+			modified = true
 		end
 		end
 
 
 		if shearMix > 0 then
 		if shearMix > 0 then
@@ -143,7 +147,10 @@ function TransformConstraint:update ()
 			local s = math_sqrt(b * b + d * d)
 			local s = math_sqrt(b * b + d * d)
 			bone.b = math_cos(r) * s
 			bone.b = math_cos(r) * s
 			bone.d = math_sin(r) * s
 			bone.d = math_sin(r) * s
+			modified = true
 		end
 		end
+		
+		if modified then bone.appliedValid = false end
 	end
 	end
 end
 end
 
 

+ 1 - 0
spine-lua/TransformConstraintData.lua

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

+ 6 - 8
spine-lua/attachments/MeshAttachment.lua

@@ -115,8 +115,6 @@ function MeshAttachment:updateWorldVertices(slot, premultipliedAlpha)
 		skeletonColor.b * slotColor.b * meshColor.b * multiplier,
 		skeletonColor.b * slotColor.b * meshColor.b * multiplier,
 		alpha)
 		alpha)
 
 
-	local x = skeleton.x
-	local y = skeleton.y
 	local deformArray = slot.attachmentVertices
 	local deformArray = slot.attachmentVertices
 	local vertices = self.vertices
 	local vertices = self.vertices
 	local worldVertices = self.worldVertices
 	local worldVertices = self.worldVertices
@@ -125,8 +123,8 @@ function MeshAttachment:updateWorldVertices(slot, premultipliedAlpha)
 		local verticesLength = #vertices
 		local verticesLength = #vertices
 		if #deformArray > 0 then vertices = deformArray end
 		if #deformArray > 0 then vertices = deformArray end
 		local bone = slot.bone;
 		local bone = slot.bone;
-		x = x + bone.worldX
-		y = y + bone.worldY
+		local x = bone.worldX
+		local y = bone.worldY
 		local a = bone.a
 		local a = bone.a
 		local b = bone.b
 		local b = bone.b
 		local c = bone.c
 		local c = bone.c
@@ -155,8 +153,8 @@ function MeshAttachment:updateWorldVertices(slot, premultipliedAlpha)
 		local b = 0
 		local b = 0
 		local n = #bones
 		local n = #bones
 		while v < n do
 		while v < n do
-			local wx = x
-			local wy = y
+			local wx = 0
+			local wy = 0
 			local nn = bones[v + 1];
 			local nn = bones[v + 1];
 			v = v + 1
 			v = v + 1
 			nn = nn + v
 			nn = nn + v
@@ -186,8 +184,8 @@ function MeshAttachment:updateWorldVertices(slot, premultipliedAlpha)
 		local f = 0
 		local f = 0
 		local n = #bones
 		local n = #bones
 		while v < n do
 		while v < n do
-			local wx = x
-			local wy = y
+			local wx = 0
+			local wy = 0
 			local nn = bones[v + 1]
 			local nn = bones[v + 1]
 			v = v + 1
 			v = v + 1
 			nn = nn + v
 			nn = nn + v

+ 2 - 2
spine-lua/attachments/RegionAttachment.lua

@@ -179,8 +179,8 @@ function RegionAttachment:updateWorldVertices (slot, premultipliedAlpha)
 	local vertices = self.vertices
 	local vertices = self.vertices
 	local offset = self.offset
 	local offset = self.offset
 	local bone = slot.bone
 	local bone = slot.bone
-	local x = skeleton.x + bone.worldX
-	local y = skeleton.y + bone.worldY
+	local x = bone.worldX
+	local y = bone.worldY
 	local a = bone.a
 	local a = bone.a
 	local b = bone.b
 	local b = bone.b
 	local c = bone.c
 	local c = bone.c

+ 6 - 8
spine-lua/attachments/VertexAttachment.lua

@@ -57,16 +57,14 @@ end
 function VertexAttachment:computeWorldVerticesWith (slot, start, count, worldVertices, offset)
 function VertexAttachment:computeWorldVerticesWith (slot, start, count, worldVertices, offset)
 	count = count + offset
 	count = count + offset
 	local skeleton = slot.bone.skeleton
 	local skeleton = slot.bone.skeleton
-	local x = skeleton.x
-	local y = skeleton.y
 	local deformArray = slot.attachmentVertices
 	local deformArray = slot.attachmentVertices
 	local vertices = self.vertices
 	local vertices = self.vertices
 	local bones = self.bones
 	local bones = self.bones
 	if not bones then
 	if not bones then
 		if #deformArray > 0 then vertices = deformArray end
 		if #deformArray > 0 then vertices = deformArray end
 		local bone = slot.bone
 		local bone = slot.bone
-		x = x + bone.worldX
-		y = y + bone.worldY
+		x = bone.worldX
+		y = bone.worldY
 		local a = bone.a
 		local a = bone.a
 		local b = bone.b
 		local b = bone.b
 		local c = bone.c
 		local c = bone.c
@@ -97,8 +95,8 @@ function VertexAttachment:computeWorldVerticesWith (slot, start, count, worldVer
 		local w = offset
 		local w = offset
 		local b = skip * 3
 		local b = skip * 3
 		while w < count do
 		while w < count do
-			local wx = x
-			local wy = y
+			local wx = 0
+			local wy = 0
 			local n = bones[v + 1]
 			local n = bones[v + 1]
 			v = v + 1
 			v = v + 1
 			n = n + v
 			n = n + v
@@ -122,8 +120,8 @@ function VertexAttachment:computeWorldVerticesWith (slot, start, count, worldVer
 		local b = skip * 3
 		local b = skip * 3
 		local f = skip * 2
 		local f = skip * 2
 		while w < count do
 		while w < count do
-			local wx = x
-			local wy = y
+			local wx = 0
+			local wy = 0
 			local n = bones[v + 1]
 			local n = bones[v + 1]
 			v = v + 1
 			v = v + 1
 			n = n + v
 			n = n + v