ソースを参照

[lua] Ported additive blending, see #1060, see #1029

badlogic 7 年 前
コミット
54e99f1454
4 ファイル変更334 行追加199 行削除
  1. 4 4
      spine-corona/main.lua
  2. 269 143
      spine-lua/Animation.lua
  3. 60 51
      spine-lua/AnimationState.lua
  4. 1 1
      spine-ts/core/src/Animation.ts

+ 4 - 4
spine-corona/main.lua

@@ -81,12 +81,12 @@ function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
 	return { skeleton = skeleton, state = animationState }
 	return { skeleton = skeleton, state = animationState }
 end
 end
 
 
--- table.insert(skeletons, loadSkeleton("coin.atlas", "coin-pro.json", 240, 300, 0.4, "rotate"))
--- table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy-ess.json", 240, 300, 0.4, "walk"))
+table.insert(skeletons, loadSkeleton("coin.atlas", "coin-pro.json", 240, 300, 0.4, "rotate"))
+table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy-ess.json", 240, 300, 0.4, "walk"))
 table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
 table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
--- table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-pro.json", 240, 300, 0.8, "walk", "goblin"))
+table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-pro.json", 240, 300, 0.8, "walk", "goblin"))
 table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak"))
 table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak"))
--- table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive"))
+table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive"))
 table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow"))
 table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow"))
 
 
 local triangulator = spine.Triangulator.new()
 local triangulator = spine.Triangulator.new()

+ 269 - 143
spine-lua/Animation.lua

@@ -54,7 +54,7 @@ function Animation.new (name, timelines, duration)
 		duration = duration
 		duration = duration
 	}
 	}
 
 
-	function self:apply (skeleton, lastTime, time, loop, events, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, loop, events, alpha, blend, direction)
 		if not skeleton then error("skeleton cannot be nil.", 2) end
 		if not skeleton then error("skeleton cannot be nil.", 2) end
 
 
 		if loop and duration > 0 then
 		if loop and duration > 0 then
@@ -63,7 +63,7 @@ function Animation.new (name, timelines, duration)
 		end
 		end
 
 
 		for i,timeline in ipairs(self.timelines) do
 		for i,timeline in ipairs(self.timelines) do
-			timeline:apply(skeleton, lastTime, time, events, alpha, pose, direction)
+			timeline:apply(skeleton, lastTime, time, events, alpha, blend, direction)
 		end
 		end
 	end
 	end
 
 
@@ -113,12 +113,13 @@ local function linearSearch (values, target, step)
 	return -1
 	return -1
 end
 end
 
 
-Animation.MixPose = {
+Animation.MixBlend = {
 	setup = 0,
 	setup = 0,
-	current = 1,
-	currentLayered = 2
+	first = 1,
+	replace = 2,
+	add = 3
 }
 }
-local MixPose = Animation.MixPose
+local MixBlend = Animation.MixBlend
 
 
 Animation.MixDirection = {
 Animation.MixDirection = {
 	_in = 0, out = 1
 	_in = 0, out = 1
@@ -255,28 +256,30 @@ function Animation.RotateTimeline.new (frameCount)
 		self.frames[frameIndex + ROTATION] = degrees
 		self.frames[frameIndex + ROTATION] = degrees
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 		if time < frames[0] then
 		if time < frames[0] then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				bone.rotation = bone.data.rotation
 				bone.rotation = bone.data.rotation
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				local r = bone.data.rotation - bone.rotation
 				local r = bone.data.rotation - bone.rotation
-				r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
-				bone.rotation = bone.rotation + r * alpha
+				bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
 			end
 			end
 			return
 			return
 		end
 		end
 
 
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			if pose == MixPose.setup then
-				bone.rotation = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] * alpha
-			else
-				local r = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] - bone.rotation
+			local r = frames[zlen(frames) + PREV_ROTATION]
+			if blend == MixBlend.setup then
+				bone.rotation = bone.data.rotation + r * alpha
+			elseif blend == MixBlend.first or blend == MixBlend.replace then
+				r = r + bone.data.rotation - bone.rotation
 				r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
 				r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
 				bone.rotation = bone.rotation + r * alpha;
 				bone.rotation = bone.rotation + r * alpha;
+			elseif blend == MixBlend.add then
+				bone.rotation = bone.rotation + r * alpha;				
 			end
 			end
 			return;
 			return;
 		end
 		end
@@ -288,15 +291,14 @@ function Animation.RotateTimeline.new (frameCount)
 		local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 		local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 
 
 		local r = frames[frame + ROTATION] - prevRotation
 		local r = frames[frame + ROTATION] - prevRotation
-		r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
-		r = prevRotation + r * percent
-		if pose == MixPose.setup then
-			r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
-			bone.rotation = bone.data.rotation + r * alpha
-		else
-			r = bone.data.rotation + r - bone.rotation;
-			r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
-			bone.rotation = bone.rotation + r * alpha
+		r = prevRotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * percent
+		if blend == MixBlend.setup then
+			bone.rotation = bone.data.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
+		elseif blend == MixBlend.first or blend == MixBlend.replace then
+			r = r + bone.data.rotation - bone.rotation;
+			bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
+		elseif blend == MixBlend.add then
+			bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
 		end
 		end
 	end
 	end
 
 
@@ -329,15 +331,15 @@ function Animation.TranslateTimeline.new (frameCount)
 		self.frames[frameIndex + Y] = y
 		self.frames[frameIndex + Y] = y
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 		if time < frames[0] then 
 		if time < frames[0] then 
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				bone.x = bone.data.x
 				bone.x = bone.data.x
 				bone.y = bone.data.y
 				bone.y = bone.data.y
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				bone.x = bone.x + (bone.data.x - bone.x) * alpha
 				bone.x = bone.x + (bone.data.x - bone.x) * alpha
 				bone.y = bone.y + (bone.data.y - bone.y) * alpha
 				bone.y = bone.y + (bone.data.y - bone.y) * alpha
 			end
 			end
@@ -361,12 +363,15 @@ function Animation.TranslateTimeline.new (frameCount)
 			x = x + (frames[frame + X] - x) * percent
 			x = x + (frames[frame + X] - x) * percent
 			y = y + (frames[frame + Y] - y) * percent
 			y = y + (frames[frame + Y] - y) * percent
 		end
 		end
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			bone.x = bone.data.x + x * alpha
 			bone.x = bone.data.x + x * alpha
 			bone.y = bone.data.y + y * alpha
 			bone.y = bone.data.y + y * alpha
-		else
+		elseif blend == MixBlend.first or blend == MixBlend.replace then
 			bone.x = bone.x + (bone.data.x + x - bone.x) * alpha
 			bone.x = bone.x + (bone.data.x + x - bone.x) * alpha
 			bone.y = bone.y + (bone.data.y + y - bone.y) * alpha
 			bone.y = bone.y + (bone.data.y + y - bone.y) * alpha
+		elseif blend == MixBlend.add then
+			bone.x = bone.x + x * alpha
+			bone.y = bone.y + y * alpha
 		end
 		end
 	end
 	end
 
 
@@ -390,15 +395,15 @@ function Animation.ScaleTimeline.new (frameCount)
 		return TimelineType.scale * SHL_24 + self.boneIndex
 		return TimelineType.scale * SHL_24 + self.boneIndex
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 		if time < frames[0] then
 		if time < frames[0] then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				bone.scaleX = bone.data.scaleX
 				bone.scaleX = bone.data.scaleX
 				bone.scaleY = bone.data.scaleY
 				bone.scaleY = bone.data.scaleY
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha
 				bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha
 				bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha
 				bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha
 			end
 			end
@@ -423,28 +428,51 @@ function Animation.ScaleTimeline.new (frameCount)
 			y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY
 			y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY
 		end
 		end
 		if alpha == 1 then
 		if alpha == 1 then
-			bone.scaleX = x
-			bone.scaleY = y
+			if blend == MixBlend.add then
+				bone.scaleX = bone.scaleX + x - bone.data.scaleX
+				bone.scaleY = bone.scaleY + y - bone.data.scaleY
+			else
+				bone.scaleX = x
+				bone.scaleY = y
+			end
 		else
 		else
 			local bx = 0
 			local bx = 0
 			local by = 0
 			local by = 0
-			if pose == MixPose.setup then
-				bx = bone.data.scaleX
-				by = bone.data.scaleY
-			else
-				bx = bone.scaleX
-				by = bone.scaleY
-			end
-			-- Mixing out uses sign of setup or current pose, else use sign of key.
-			if direction == MixDirection.out then
-				x = math_abs(x) * math_signum(bx)
-				y = math_abs(y) * math_signum(by)
+			if direction == MixDirection.out then 
+				if blend == MixBlend.setup then
+					bx = bone.data.scaleX
+					by = bone.data.scaleY
+					bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bx) * alpha
+					bone.scaleY = by + (math_abs(y) * math_signum(by) - by) * alpha
+				elseif blend == MixBlend.first or blend == MixBlend.replace then
+					bx = bone.scaleX
+					by = bone.scaleY
+					bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bx) * alpha
+					bone.scaleY = by + (math_abs(y) * math_signum(by) - by) * alpha
+				elseif blend == MixBlend.add then
+					bx = bone.scaleX
+					by = bone.scaleY
+					bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bone.data.scaleX) * alpha
+					bone.scaleY = by + (math_abs(y) * math_signum(by) - bone.data.scaleY) * alpha
+				end
 			else
 			else
-				bx = math_abs(bx) * math_signum(x)
-				by = math_abs(by) * math_signum(y)
+				if blend == MixBlend.setup then
+					bx = math_abs(bone.data.scaleX) * math_signum(x)
+					by = math_abs(bone.data.scaleY) * math_signum(y)
+					bone.scaleX = bx + (x - bx) * alpha
+					bone.scaleY = by + (y - by) * alpha
+				elseif blend == MixBlend.first or blend == MixBlend.replace then
+					bx = math_abs(bone.scaleX) * math_signum(x)
+					by = math_abs(bone.scaleY) * math_signum(y)
+					bone.scaleX = bx + (x - bx) * alpha
+					bone.scaleY = by + (y - by) * alpha
+				elseif blend == MixBlend.add then
+					bx = math_signum(x)
+					by = math_signum(y)
+					bone.scaleX = math_abs(bone.scaleX) * bx + (x - math_abs(bone.data.scaleX) * bx) * alpha
+					bone.scaleY = math_abs(bone.scaleY) * by + (y - math_abs(bone.data.scaleY) * by) * alpha
+				end
 			end
 			end
-			bone.scaleX = bx + (x - bx) * alpha
-			bone.scaleY = by + (y - by) * alpha
 		end
 		end
 	end
 	end
 
 
@@ -468,15 +496,15 @@ function Animation.ShearTimeline.new (frameCount)
 		return TimelineType.shear * SHL_24 + self.boneIndex
 		return TimelineType.shear * SHL_24 + self.boneIndex
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 		if time < frames[0] then
 		if time < frames[0] then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				bone.shearX = bone.data.shearX
 				bone.shearX = bone.data.shearX
 				bone.shearY = bone.data.shearY
 				bone.shearY = bone.data.shearY
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha
 				bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha
 				bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha
 				bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha
 			end
 			end
@@ -500,12 +528,15 @@ function Animation.ShearTimeline.new (frameCount)
 			x = x + (frames[frame + X] - x) * percent
 			x = x + (frames[frame + X] - x) * percent
 			y = y + (frames[frame + Y] - y) * percent
 			y = y + (frames[frame + Y] - y) * percent
 		end
 		end
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			bone.shearX = bone.data.shearX + x * alpha
 			bone.shearX = bone.data.shearX + x * alpha
 			bone.shearY = bone.data.shearY + y * alpha
 			bone.shearY = bone.data.shearY + y * alpha
-		else
+		elseif blend == MixBlend.first or blend == MixBlend.replace then
 			bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha
 			bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha
 			bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha
 			bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha
+		elseif blend == MixBlend.add then
+			bone.shearX = bone.shearX + x * alpha
+			bone.shearY = bone.shearY + y * alpha
 		end
 		end
 	end
 	end
 
 
@@ -544,13 +575,13 @@ function Animation.ColorTimeline.new (frameCount)
 		self.frames[frameIndex + A] = a
 		self.frames[frameIndex + A] = a
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 		local slot = skeleton.slots[self.slotIndex]
 		local slot = skeleton.slots[self.slotIndex]
 		if time < frames[0] then 
 		if time < frames[0] then 
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				slot.color:setFrom(slot.data.color)
 				slot.color:setFrom(slot.data.color)
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				local color = slot.color
 				local color = slot.color
 				local setup = slot.data.color
 				local setup = slot.data.color
 				color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
 				color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
@@ -586,7 +617,7 @@ function Animation.ColorTimeline.new (frameCount)
 			slot.color:set(r, g, b, a)
 			slot.color:set(r, g, b, a)
 		else
 		else
 			local color = slot.color
 			local color = slot.color
-			if pose == MixPose.setup then color:setFrom(slot.data.color) end
+			if blend == MixBlend.setup then color:setFrom(slot.data.color) end
 			color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha)
 			color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha)
 		end
 		end
 	end
 	end
@@ -635,14 +666,14 @@ function Animation.TwoColorTimeline.new (frameCount)
 		self.frames[frameIndex + B2] = b2
 		self.frames[frameIndex + B2] = b2
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 		local slot = skeleton.slots[self.slotIndex]
 		local slot = skeleton.slots[self.slotIndex]
 		if time < frames[0] then 
 		if time < frames[0] then 
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				slot.color:setFrom(slot.data.color)
 				slot.color:setFrom(slot.data.color)
 				slot.darkColor:setFrom(slot.data.darkColor)
 				slot.darkColor:setFrom(slot.data.darkColor)
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				local light = slot.color
 				local light = slot.color
 				local dark = slot.darkColor
 				local dark = slot.darkColor
 				local setupLight = slot.data.color
 				local setupLight = slot.data.color
@@ -692,7 +723,7 @@ function Animation.TwoColorTimeline.new (frameCount)
 		else
 		else
 			local light = slot.color
 			local light = slot.color
 			local dark = slot.darkColor
 			local dark = slot.darkColor
-			if pose == MixPose.setup then 
+			if blend == MixBlend.setup then 
 				light:setFrom(slot.data.color)
 				light:setFrom(slot.data.color)
 				dark:setFrom(slot.data.darkColor)
 				dark:setFrom(slot.data.darkColor)
 			end
 			end
@@ -726,10 +757,10 @@ function Animation.AttachmentTimeline.new (frameCount)
 		return TimelineType.attachment * SHL_24 + self.slotIndex
 		return TimelineType.attachment * SHL_24 + self.slotIndex
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local slot = skeleton.slots[self.slotIndex]
 		local slot = skeleton.slots[self.slotIndex]
 		local attachmentName
 		local attachmentName
-		if direction == MixDirection.out and pose == MixPose.setup then
+		if direction == MixDirection.out and blend == MixBlend.setup then
 			attachmentName = slot.data.attachmentName
 			attachmentName = slot.data.attachmentName
 			if not attachmentName then
 			if not attachmentName then
 				slot:setAttachment(nil)
 				slot:setAttachment(nil)
@@ -741,7 +772,7 @@ function Animation.AttachmentTimeline.new (frameCount)
 		
 		
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then 
 		if time < frames[0] then 
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup or blend == MixBlend.first then
 				attachmentName = slot.data.attachmentName
 				attachmentName = slot.data.attachmentName
 				if not attachmentName then
 				if not attachmentName then
 					slot:setAttachment(nil)
 					slot:setAttachment(nil)
@@ -788,7 +819,7 @@ function Animation.DeformTimeline.new (frameCount)
 		self.frameVertices[frameIndex] = vertices
 		self.frameVertices[frameIndex] = vertices
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local slot = skeleton.slots[self.slotIndex]
 		local slot = skeleton.slots[self.slotIndex]
 		local slotAttachment = slot.attachment
 		local slotAttachment = slot.attachment
 		if not slotAttachment then return end
 		if not slotAttachment then return end
@@ -797,17 +828,17 @@ function Animation.DeformTimeline.new (frameCount)
 
 
 		local frames = self.frames
 		local frames = self.frames
 		local verticesArray = slot.attachmentVertices
 		local verticesArray = slot.attachmentVertices
-    if #(verticesArray) == 0 then alpha = 1 end
+    if #(verticesArray) == 0 then blend = MixBlend.setup end
 
 
 		local frameVertices = self.frameVertices
 		local frameVertices = self.frameVertices
 		local vertexCount = #(frameVertices[0])		
 		local vertexCount = #(frameVertices[0])		
 		
 		
 		if time < frames[0] then
 		if time < frames[0] then
 			local vertexAttachment = slotAttachment;
 			local vertexAttachment = slotAttachment;
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
         slot.attachmentVertices = {}
         slot.attachmentVertices = {}
         return;
         return;
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
         if (alpha == 1) then
         if (alpha == 1) then
           slot.attachmentVertices = {}
           slot.attachmentVertices = {}
           return;
           return;
@@ -837,37 +868,90 @@ function Animation.DeformTimeline.new (frameCount)
 		if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
 			local lastVertices = frameVertices[zlen(frames) - 1]
 			local lastVertices = frameVertices[zlen(frames) - 1]
 			if alpha == 1 then
 			if alpha == 1 then
-				-- Vertex positions or deform offsets, no alpha.
-				local i = 1
-				while i <= vertexCount do
-					vertices[i] = lastVertices[i]
-					i = i + 1
-				end
-			elseif pose == MixPose.setup then
-				local vertexAttachment = slotAttachment
-				if vertexAttachment.bones == nil then
-					-- Unweighted vertex positions, with alpha.
-					local setupVertices = vertexAttachment.vertices
-					local i = 1
-					while i <= vertexCount do
-						local setup = setupVertices[i]
-						vertices[i] = setup + (lastVertices[i] - setup) * alpha
-						i = i + 1
+				if blend == MixBlend.add then
+					local vertexAttachment = slotAttachment
+					if vertexAttachment.bones == nil then
+						-- Unweighted vertex positions, with alpha.
+						local setupVertices = vertexAttachment.vertices
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + lastVertices[i] - setupVertices[i]
+							i = i + 1
+						end
+					else
+						-- Weighted deform offsets, with alpha.
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + lastVertices[i]
+							i = i + 1
+						end
 					end
 					end
 				else
 				else
-					-- Weighted deform offsets, with alpha.
 					local i = 1
 					local i = 1
 					while i <= vertexCount do
 					while i <= vertexCount do
-						vertices[i] = lastVertices[i] * alpha
+						vertices[i] = lastVertices[i]
 						i = i + 1
 						i = i + 1
 					end
 					end
 				end
 				end
 			else
 			else
-				-- Vertex positions or deform offsets, with alpha.
-				local i = 1
-				while i <= vertexCount do
-					vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha
-					i = i + 1
+				if blend == MixBlend.setup then
+					local vertexAttachment = slotAttachment
+					if vertexAttachment.bones == nil then
+						-- Unweighted vertex positions, with alpha.
+						local setupVertices = vertexAttachment.vertices
+						local i = 1
+						while i <= vertexCount do
+							local setup = setupVertices[i]
+							vertices[i] = setup + (lastVertices[i] - setup) * alpha
+							i = i + 1
+						end
+					else
+						-- Weighted deform offsets, with alpha.
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = lastVertices[i] * alpha
+							i = i + 1
+						end
+					end
+				elseif blend == MixBlend.first or blend == MixBlend.replace then
+					local i = 1
+					while i <= vertexCount do
+						vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha
+						i = i + 1
+					end
+					local vertexAttachment = slotAttachment
+					if vertexAttachment.bones == nil then
+						local setupVertices = vertexAttachment.vertices
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + (lastVertices[i] - setupVertices[i]) * alpha
+							i = i + 1
+						end
+					else
+						-- Weighted deform offsets, with alpha.
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + lastVertices[i] * alpha
+							i = i + 1
+						end
+					end
+				elseif blend == MixBlend.add then
+					local vertexAttachment = slotAttachment
+					if vertexAttachment.bones == nil then
+						local setupVertices = vertexAttachment.vertices
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + (lastVertices[i] - setupVertices[i]) * alpha
+							i = i + 1
+						end
+					else
+						-- Weighted deform offsets, with alpha.
+						local i = 1
+						while i <= vertexCount do
+							vertices[i] = vertices[i] + lastVertices[i] * alpha
+							i = i + 1
+						end
+					end
 				end
 				end
 			end
 			end
 			return;
 			return;
@@ -881,41 +965,82 @@ function Animation.DeformTimeline.new (frameCount)
 		local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
 		local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
 
 
 		if alpha == 1 then
 		if alpha == 1 then
-			-- Vertex positions or deform offsets, no alpha.
-			local i = 1
-			while i <= vertexCount do
-				local prev = prevVertices[i]
-				vertices[i] = prev + (nextVertices[i] - prev) * percent
-				i = i + 1
-			end
-		elseif pose == MixPose.setup then
-			local vertexAttachment = slotAttachment
-			if vertexAttachment.bones == nil then
-				-- Unweighted vertex positions, with alpha.
-				local setupVertices = vertexAttachment.vertices
+			if blend == MixBlend.add then
+				local vertexAttachment = slotAttachment
+				if vertexAttachment.bones == nil then
+					-- Unweighted vertex positions, with alpha.
+					local setupVertices = vertexAttachment.vertices
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						vertices[i] = vertices[i] + prev + (nextVertices[i] - prev) * precent - setupVertices[i]
+						i = i + 1
+					end
+				else
+					-- Weighted deform offsets, with alpha.
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						vertices[i] = vertices[i] + prev + (nextVertices[i] - prev) * percent
+						i = i + 1
+					end
+				end
+			else
 				local i = 1
 				local i = 1
 				while i <= vertexCount do
 				while i <= vertexCount do
 					local prev = prevVertices[i]
 					local prev = prevVertices[i]
-					local setup = setupVertices[i]
-					vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha
+					vertices[i] = prev + (nextVertices[i] - prev) * percent
 					i = i + 1
 					i = i + 1
 				end
 				end
-			else
-				-- Weighted deform offsets, with alpha.
+			end
+		else
+			if blend == MixBlend.setup then
+				local vertexAttachment = slotAttachment
+				if vertexAttachment.bones == nil then
+					-- Unweighted vertex positions, with alpha.
+					local setupVertices = vertexAttachment.vertices
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						local setup = setupVertices[i]
+						vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha
+						i = i + 1
+					end
+				else
+					-- Weighted deform offsets, with alpha.
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha
+						i = i + 1
+					end
+				end
+			elseif blend == MixBlend.first or blend == MixBlend.replace then
 				local i = 1
 				local i = 1
 				while i <= vertexCount do
 				while i <= vertexCount do
 					local prev = prevVertices[i]
 					local prev = prevVertices[i]
-					vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha
+					vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha
 					i = i + 1
 					i = i + 1
 				end
 				end
-			end
-		else
-			-- Vertex positions or deform offsets, with alpha.
-			local i = 1
-			while i <= vertexCount do
-				local prev = prevVertices[i]
-				vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha
-				i = i + 1
+			elseif blend == MixBlend.add then
+				local vertexAttachment = slotAttachment
+				if vertexAttachment.bones == nil then
+					local setupVertices = vertexAttachment.vertices
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha
+						i = i + 1
+					end
+				else
+					-- Weighted deform offsets, with alpha.
+					local i = 1
+					while i <= vertexCount do
+						local prev = prevVertices[i]
+						vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent) * alpha
+						i = i + 1
+					end
+				end
 			end
 			end
 		end
 		end
 	end
 	end
@@ -945,14 +1070,14 @@ function Animation.EventTimeline.new (frameCount)
 	end
 	end
 
 
 	-- Fires events for frames > lastTime and <= time.
 	-- Fires events for frames > lastTime and <= time.
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		if not firedEvents then return end
 		if not firedEvents then return end
 
 
 		local frames = self.frames
 		local frames = self.frames
 		local frameCount = zlen(frames)
 		local frameCount = zlen(frames)
 
 
 		if lastTime > time then -- Fire events after last time for looped animations.
 		if lastTime > time then -- Fire events after last time for looped animations.
-			self:apply(skeleton, lastTime, 999999, firedEvents, alpha, pose, direction)
+			self:apply(skeleton, lastTime, 999999, firedEvents, alpha, blend, direction)
 			lastTime = -1
 			lastTime = -1
 		elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
 		elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
 			return
 			return
@@ -1001,18 +1126,19 @@ function Animation.DrawOrderTimeline.new (frameCount)
 		self.drawOrders[frameIndex] = drawOrder
 		self.drawOrders[frameIndex] = drawOrder
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local drawOrder = skeleton.drawOrder
 		local drawOrder = skeleton.drawOrder
 		local slots = skeleton.slots
 		local slots = skeleton.slots
-		if mixingOut and setupPose then
+		if direction == MixDirection.out and blend == MixBlend.setup then
 			for i,slot in ipairs(slots) do
 			for i,slot in ipairs(slots) do
 				drawOrder[i] = slots[i]
 				drawOrder[i] = slots[i]
 			end
 			end
 			return;
 			return;
 		end
 		end
+		
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then 
 		if time < frames[0] then 
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup or blend == MixBlend.first then
 				for i,slot in ipairs(slots) do
 				for i,slot in ipairs(slots) do
 					drawOrder[i] = slots[i]
 					drawOrder[i] = slots[i]
 				end
 				end
@@ -1068,15 +1194,15 @@ function Animation.IkConstraintTimeline.new (frameCount)
 		self.frames[frameIndex + BEND_DIRECTION] = bendDirection
 		self.frames[frameIndex + BEND_DIRECTION] = bendDirection
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
 		local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
 		if time < frames[0] then
 		if time < frames[0] then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.mix = constraint.data.mix
 				constraint.mix = constraint.data.mix
 				constraint.bendDirection = constraint.data.bendDirection
 				constraint.bendDirection = constraint.data.bendDirection
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
 				constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
 				constraint.bendDirection = constraint.data.bendDirection
 				constraint.bendDirection = constraint.data.bendDirection
 			end
 			end
@@ -1084,7 +1210,7 @@ function Animation.IkConstraintTimeline.new (frameCount)
 		end
 		end
 
 
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
 				constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
 				if direction == MixDirection.out then 
 				if direction == MixDirection.out then 
 					constraint.bendDirection = constraint.data.bendDirection
 					constraint.bendDirection = constraint.data.bendDirection
@@ -1105,7 +1231,7 @@ function Animation.IkConstraintTimeline.new (frameCount)
 		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
 		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
 				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 
 
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
 			constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
 			if direction == MixDirection.out then
 			if direction == MixDirection.out then
 				constraint.bendDirection = constraint.data.bendDirection
 				constraint.bendDirection = constraint.data.bendDirection
@@ -1153,18 +1279,18 @@ function Animation.TransformConstraintTimeline.new (frameCount)
 		self.frames[frameIndex + SHEAR] = shearMix
 		self.frames[frameIndex + SHEAR] = shearMix
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
 		local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
 		if time < frames[0] then
 		if time < frames[0] then
 			local data = constraint.data
 			local data = constraint.data
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.rotateMix = data.rotateMix
 				constraint.rotateMix = data.rotateMix
 				constraint.translateMix = data.translateMix
 				constraint.translateMix = data.translateMix
 				constraint.scaleMix = data.scaleMix
 				constraint.scaleMix = data.scaleMix
 				constraint.shearMix = data.shearMix
 				constraint.shearMix = data.shearMix
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha
 				constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha
 				constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha
 				constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha
 				constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha
 				constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha
@@ -1199,7 +1325,7 @@ function Animation.TransformConstraintTimeline.new (frameCount)
 			scale = scale + (frames[frame + SCALE] - scale) * percent
 			scale = scale + (frames[frame + SCALE] - scale) * percent
 			shear = shear + (frames[frame + SHEAR] - shear) * percent
 			shear = shear + (frames[frame + SHEAR] - shear) * percent
 		end
 		end
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			local data = constraint.data
 			local data = constraint.data
 			constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha
 			constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha
 			constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha
 			constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha
@@ -1239,14 +1365,14 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
 		self.frames[frameIndex + VALUE] = value
 		self.frames[frameIndex + VALUE] = value
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		if (time < frames[0]) then
 		if (time < frames[0]) then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.position = constraint.data.position	
 				constraint.position = constraint.data.position	
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha
 				constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha
 			end
 			end
 			return
 			return
@@ -1265,7 +1391,7 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
 
 
 			position = position + (frames[frame + VALUE] - position) * percent
 			position = position + (frames[frame + VALUE] - position) * percent
 		end
 		end
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
 			constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
 		else
 		else
 			constraint.position = constraint.position + (position - constraint.position) * alpha
 			constraint.position = constraint.position + (position - constraint.position) * alpha
@@ -1298,14 +1424,14 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
 		self.frames[frameIndex + VALUE] = value
 		self.frames[frameIndex + VALUE] = value
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		if (time < frames[0]) then
 		if (time < frames[0]) then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.spacing = constraint.data.spacing
 				constraint.spacing = constraint.data.spacing
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha
 				constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha
 			end
 			end
 			return
 			return
@@ -1325,7 +1451,7 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
 			spacing = spacing + (frames[frame + VALUE] - spacing) * percent
 			spacing = spacing + (frames[frame + VALUE] - spacing) * percent
 		end
 		end
 
 
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
 			constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
 		else
 		else
 			constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
 			constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
@@ -1361,15 +1487,15 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
 		self.frames[frameIndex + TRANSLATE] = translateMix
 		self.frames[frameIndex + TRANSLATE] = translateMix
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
 		local frames = self.frames
 		local frames = self.frames
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		if (time < frames[0]) then
 		if (time < frames[0]) then
-			if pose == MixPose.setup then
+			if blend == MixBlend.setup then
 				constraint.rotateMix = constraint.data.rotateMix
 				constraint.rotateMix = constraint.data.rotateMix
 				constraint.translateMix = constraint.data.translateMix
 				constraint.translateMix = constraint.data.translateMix
-			elseif pose == MixPose.current then
+			elseif blend == MixBlend.first then
 				constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha
 				constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha
 				constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha
 				constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha
 			end
 			end
@@ -1394,7 +1520,7 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
 			translate = translate + (frames[frame + TRANSLATE] - translate) * percent
 			translate = translate + (frames[frame + TRANSLATE] - translate) * percent
 		end
 		end
 
 
-		if pose == MixPose.setup then
+		if blend == MixBlend.setup then
 			constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha
 			constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha
 			constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha
 			constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha
 		else
 		else

+ 60 - 51
spine-lua/AnimationState.lua

@@ -32,7 +32,7 @@ local setmetatable = setmetatable
 local table_insert = table.insert
 local table_insert = table.insert
 local utils = require "spine-lua.utils"
 local utils = require "spine-lua.utils"
 local Animation = require "spine-lua.Animation"
 local Animation = require "spine-lua.Animation"
-local MixPose = Animation.MixPose
+local MixBlend = Animation.MixBlend
 local MixDirection = Animation.MixDirection
 local MixDirection = Animation.MixDirection
 local AnimationStateData = require "spine-lua.AnimationStateData"
 local AnimationStateData = require "spine-lua.AnimationStateData"
 local math_min = math.min
 local math_min = math.min
@@ -175,6 +175,7 @@ function TrackEntry.new ()
 		animationStart = 0, animationEnd = 0, animationLast = 0, nextAnimationLast = 0,
 		animationStart = 0, animationEnd = 0, animationLast = 0, nextAnimationLast = 0,
 		delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0,
 		delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0,
 		alpha = 0, mixTime = 0, mixDuration = 0, interruptAlpha = 0, totalAlpha = 0,
 		alpha = 0, mixTime = 0, mixDuration = 0, interruptAlpha = 0, totalAlpha = 0,
+		mixBlend = MixBlend.replace,
 		timelineData = {},
 		timelineData = {},
 		timelineDipMix = {},
 		timelineDipMix = {},
 		timelinesRotation = {}
 		timelinesRotation = {}
@@ -374,13 +375,13 @@ function AnimationState:apply (skeleton)
 	for i,current in pairs(tracks) do
 	for i,current in pairs(tracks) do
 		if not (current == nil or current.delay > 0) then
 		if not (current == nil or current.delay > 0) then
       applied = true
       applied = true
-			local currrentPose = MixPose.currentLayered
-			if i == 0 then currentPose = MixPose.current end
+			local blend = current.mixBlend
+			if i == 0 then blend = MixBlend.first end
 			
 			
 			-- Apply mixing from entries first.
 			-- Apply mixing from entries first.
 			local mix = current.alpha
 			local mix = current.alpha
 			if current.mixingFrom then 
 			if current.mixingFrom then 
-				mix = mix * self:applyMixingFrom(current, skeleton, currentPose)
+				mix = mix * self:applyMixingFrom(current, skeleton, blend)
 			elseif current.trackTime >= current.trackEnd and current.next == nil then
 			elseif current.trackTime >= current.trackEnd and current.next == nil then
 				mix = 0
 				mix = 0
 			end
 			end
@@ -389,9 +390,9 @@ function AnimationState:apply (skeleton)
 			local animationLast = current.animationLast
 			local animationLast = current.animationLast
 			local animationTime = current:getAnimationTime()
 			local animationTime = current:getAnimationTime()
 			local timelines = current.animation.timelines
 			local timelines = current.animation.timelines
-			if mix == 1 then
+			if mix == 1 or blend == MixBlend.add then
 				for i,timeline in ipairs(timelines) do
 				for i,timeline in ipairs(timelines) do
-					timeline:apply(skeleton, animationLast, animationTime, events, 1, MixPose.setup, MixDirection._in)
+					timeline:apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection._in)
 				end
 				end
 			else
 			else
 				local timelineData = current.timelineData
 				local timelineData = current.timelineData
@@ -399,14 +400,14 @@ function AnimationState:apply (skeleton)
 				local timelinesRotation = current.timelinesRotation
 				local timelinesRotation = current.timelinesRotation
 
 
 				for i,timeline in ipairs(timelines) do
 				for i,timeline in ipairs(timelines) do
-					local pose = MixPose.currentPose
-					if timelineData[i] >= FIRST then pose = MixPose.setup end
+					local timelineBlend = MixBlend.setup
+					if timelineData[i] == SUBSEQUENT then timelineBlend = blend end
 					
 					
 					if timeline.type == Animation.TimelineType.rotate then
 					if timeline.type == Animation.TimelineType.rotate then
-						self:applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, i * 2,
+						self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, i * 2,
 							firstFrame) -- FIXME passing ii * 2, indexing correct?
 							firstFrame) -- FIXME passing ii * 2, indexing correct?
 					else
 					else
-						timeline:apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection._in)
+						timeline:apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, MixDirection._in)
 					end
 					end
 				end
 				end
 			end
 			end
@@ -421,17 +422,18 @@ function AnimationState:apply (skeleton)
   return applied
   return applied
 end
 end
 
 
-function AnimationState:applyMixingFrom (to, skeleton, currentPose)
+function AnimationState:applyMixingFrom (to, skeleton, blend)
 	local from = to.mixingFrom
 	local from = to.mixingFrom
-	if from.mixingFrom then self:applyMixingFrom(from, skeleton, currentPose) end
+	if from.mixingFrom then self:applyMixingFrom(from, skeleton, blend) end
 
 
 	local mix = 0
 	local mix = 0
 	if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes.
 	if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes.
 		mix = 1
 		mix = 1
-    currentPose = MixPose.setup
+    if blend == MixBlend.first then blend = MixBlend.setup end
 	else
 	else
 		mix = to.mixTime / to.mixDuration
 		mix = to.mixTime / to.mixDuration
 		if mix > 1 then mix = 1 end
 		if mix > 1 then mix = 1 end
+		if blend ~= MixBlend.first then blend = from.mixBlend end
 	end
 	end
 
 
 	local events = nil
 	local events = nil
@@ -441,44 +443,50 @@ function AnimationState:applyMixingFrom (to, skeleton, currentPose)
 	local animationLast = from.animationLast
 	local animationLast = from.animationLast
 	local animationTime = from:getAnimationTime()
 	local animationTime = from:getAnimationTime()
 	local timelines = from.animation.timelines
 	local timelines = from.animation.timelines
-	local timelineData = from.timelineData
-	local timelineDipMix = from.timelineDipMix
-
-	local firstFrame = #from.timelinesRotation == 0
-	local timelinesRotation = from.timelinesRotation
-
-	local pose = MixPose.setup
 	local alphaDip = from.alpha * to.interruptAlpha
 	local alphaDip = from.alpha * to.interruptAlpha
 	local alphaMix = alphaDip * (1 - mix)
 	local alphaMix = alphaDip * (1 - mix)
-	local alpha = 0
-	from.totalAlpha = 0;
-
-	for i,timeline in ipairs(timelines) do
-		local skipSubsequent = false;
-		if timelineData[i] == SUBSEQUENT then
-			if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
-			if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
-			pose = currentPose
-			alpha = alphaMix
-		elseif timelineData[i] == FIRST then
-			pose = MixPose.setup
-			alpha = alphaMix
-		elseif timelineData[i] == DIP then
-			pose = MixPose.setup
-			alpha = alphaDip
-		else
-			pose = MixPose.setup
-			alpha = alphaDip
-			local dipMix = timelineDipMix[i]
-			alpha = alpha * math_max(0, 1 - dipMix.mixtime / dipMix.mixDuration)
+	
+	if blend == MixBlend.add then
+		for i,timeline in ipairs(timelines) do
+			timeline:apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.out)
 		end
 		end
+	else
+		local timelineData = from.timelineData
+		local timelineDipMix = from.timelineDipMix
+
+		local firstFrame = #from.timelinesRotation == 0
+		local timelinesRotation = from.timelinesRotation
 		
 		
-		if not skipSubsequent then
-			from.totalAlpha = from.totalAlpha + alpha
-			if timeline.type == Animation.TimelineType.rotate then
-				self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i * 2, firstFrame)
+		from.totalAlpha = 0;
+
+		for i,timeline in ipairs(timelines) do
+			local skipSubsequent = false;
+			local timelineBlend = MixBlend.setup
+			local alpha = 0
+			if timelineData[i] == SUBSEQUENT then
+				if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
+				if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
+				timelineBlend = blend
+				alpha = alphaMix
+			elseif timelineData[i] == FIRST then
+				timelineBlend = MixBlend.setup
+				alpha = alphaMix
+			elseif timelineData[i] == DIP then
+				timelineBlend = MixBlend.setup
+				alpha = alphaDip
 			else
 			else
-				timeline:apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.out)
+				timelineBlend = MixBlend.setup
+				local dipMix = timelineDipMix[i]
+				alpha = alphaDip * math_max(0, 1 - dipMix.mixtime / dipMix.mixDuration)
+			end
+			
+			if not skipSubsequent then
+				from.totalAlpha = from.totalAlpha + alpha
+				if timeline.type == Animation.TimelineType.rotate then
+					self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
+				else
+					timeline:apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, MixDirection.out)
+				end
 			end
 			end
 		end
 		end
 	end
 	end
@@ -491,14 +499,14 @@ function AnimationState:applyMixingFrom (to, skeleton, currentPose)
 	return mix
 	return mix
 end
 end
 
 
-function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame)
+function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame)
 	if firstFrame then 
 	if firstFrame then 
 		timelinesRotation[i] = 0
 		timelinesRotation[i] = 0
 		timelinesRotation[i+1] = 0
 		timelinesRotation[i+1] = 0
 	end
 	end
 	
 	
   if alpha == 1 then
   if alpha == 1 then
-    timeline:apply(skeleton, 0, time, nil, 1, pose, MixDirection._in)
+    timeline:apply(skeleton, 0, time, nil, 1, blend, MixDirection._in)
     return
     return
   end
   end
 
 
@@ -506,7 +514,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, po
   local frames = rotateTimeline.frames
   local frames = rotateTimeline.frames
   local bone = skeleton.bones[rotateTimeline.boneIndex]
   local bone = skeleton.bones[rotateTimeline.boneIndex]
   if time < frames[0] then
   if time < frames[0] then
-		if pose == MixPose.setup then bone.rotation = bone.data.rotation end
+		if blend == MixBlend.setup then bone.rotation = bone.data.rotation end
 		return
 		return
 	end
 	end
 
 
@@ -529,7 +537,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, po
 
 
   -- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
   -- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
   local r1 = bone.rotation
   local r1 = bone.rotation
-  if pose == MixPose.setup then r1 = bone.data.rotation end
+  if blend == MixBlend.setup then r1 = bone.data.rotation end
   local total = 0
   local total = 0
   local diff = r2 - r1
   local diff = r2 - r1
   if diff == 0 then
   if diff == 0 then
@@ -797,6 +805,7 @@ function AnimationState:trackEntry (trackIndex, animation, loop, last)
   else
   else
     entry.mixDuration = data:getMix(last.animation, animation)
     entry.mixDuration = data:getMix(last.animation, animation)
   end
   end
+	entry.mixBlend = MixBlend.replace
   return entry
   return entry
 end
 end
 
 
@@ -818,7 +827,7 @@ function AnimationState:_animationsChanged ()
 	local mixingTo = self.mixingTo
 	local mixingTo = self.mixingTo
 	  
 	  
 	for i, entry in pairs(self.tracks) do
 	for i, entry in pairs(self.tracks) do
-		if entry then
+		if entry and (i == 0 or entry.mixBlend ~= MixBlend.add) then
 			entry:setTimelineData(nil, mixingTo, propertyIDs)			
 			entry:setTimelineData(nil, mixingTo, propertyIDs)			
 		end
 		end
 	end
 	end

+ 1 - 1
spine-ts/core/src/Animation.ts

@@ -833,7 +833,7 @@ module spine {
 					case MixBlend.first:
 					case MixBlend.first:
 					case MixBlend.replace:
 					case MixBlend.replace:
 						for (let i = 0; i < vertexCount; i++)
 						for (let i = 0; i < vertexCount; i++)
-						vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
+							vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
 					case MixBlend.add:
 					case MixBlend.add:
 						let vertexAttachment = slotAttachment as VertexAttachment;
 						let vertexAttachment = slotAttachment as VertexAttachment;
 						if (vertexAttachment.bones == null) {
 						if (vertexAttachment.bones == null) {