浏览代码

[lua] Ported changes to Animation.java, main.lua updated to use new callbacks

badlogic 8 年之前
父节点
当前提交
e586b0fd09
共有 3 个文件被更改,包括 481 次插入254 次删除
  1. 26 9
      spine-corona/main.lua
  2. 454 244
      spine-lua/Animation.lua
  3. 1 1
      spine-lua/SkeletonJson.lua

+ 26 - 9
spine-corona/main.lua

@@ -32,8 +32,8 @@ function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
 
 
 	-- create an animation state object to apply animations to the skeleton
 	-- create an animation state object to apply animations to the skeleton
 	local animationStateData = spine.AnimationStateData.new(skeletonData)
 	local animationStateData = spine.AnimationStateData.new(skeletonData)
+	animationStateData.defaultMix = 0.2
 	local animationState = spine.AnimationState.new(animationStateData)
 	local animationState = spine.AnimationState.new(animationStateData)
-	animationState:setAnimationByName(0, animation, true)
 
 
 	-- set the skeleton invisible
 	-- set the skeleton invisible
 	skeleton.group.isVisible = false
 	skeleton.group.isVisible = false
@@ -42,18 +42,26 @@ function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
 	skeleton.group.name = jsonFile
 	skeleton.group.name = jsonFile
 
 
 	-- set some event callbacks
 	-- set some event callbacks
-	animationState.onStart = function (trackIndex)
-		print(trackIndex.." start: "..animationState:getCurrent(trackIndex).animation.name)
+	animationState.onStart = function (entry)
+		print(entry.trackIndex.." start: "..entry.animation.name)
+	end
+	animationState.onInterrupt = function (entry)
+		print(entry.trackIndex.." interrupt: "..entry.animation.name)
 	end
 	end
-	animationState.onEnd = function (trackIndex)
-		print(trackIndex.." end: "..animationState:getCurrent(trackIndex).animation.name)
+	animationState.onEnd = function (entry)
+		print(entry.trackIndex.." end: "..entry.animation.name)
 	end
 	end
-	animationState.onComplete = function (trackIndex, loopCount)
-		print(trackIndex.." complete: "..animationState:getCurrent(trackIndex).animation.name..", "..loopCount)
+	animationState.onComplete = function (entry)
+		print(entry.trackIndex.." complete: "..entry.animation.name)
 	end
 	end
-	animationState.onEvent = function (trackIndex, event)
-		print(trackIndex.." event: "..animationState:getCurrent(trackIndex).animation.name..", "..event.data.name..", "..event.intValue..", "..event.floatValue..", '"..(event.stringValue or "").."'")
+	animationState.onDispose = function (entry)
+		print(entry.trackIndex.." dispose: "..entry.animation.name)
 	end
 	end
+	animationState.onEvent = function (entry, event)
+		print(entry.trackIndex.." event: "..entry.animation.name..", "..event.data.name..", "..event.intValue..", "..event.floatValue..", '"..(event.stringValue or "").."'")
+	end
+	
+	animationState:setAnimationByName(0, animation, true)
 
 
 	-- return the skeleton an animation state
 	-- return the skeleton an animation state
 	return { skeleton = skeleton, state = animationState }
 	return { skeleton = skeleton, state = animationState }
@@ -85,6 +93,15 @@ Runtime:addEventListener("enterFrame", function (event)
 	-- print(skeleton.batches)
 	-- print(skeleton.batches)
 end)
 end)
 
 
+Runtime:addEventListener("key", function(event)
+	if activeSkeleton == 2 and event.phase == "down" then
+		state = skeletons[activeSkeleton].state
+		state:setAnimationByName(0, "Jump", false)
+		state:addAnimationByName(0, "walk", true, 0)
+	end
+	return false
+end)
+
 Runtime:addEventListener("tap", function(event)
 Runtime:addEventListener("tap", function(event)
 	skeletons[activeSkeleton].skeleton.group.isVisible = false
 	skeletons[activeSkeleton].skeleton.group.isVisible = false
 	activeSkeleton = activeSkeleton + 1
 	activeSkeleton = activeSkeleton + 1

+ 454 - 244
spine-lua/Animation.lua

@@ -21,7 +21,7 @@
 -- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 -- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 -- EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 -- EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS Owelp,F
 -- USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 -- USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 -- IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 -- IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
@@ -36,6 +36,9 @@
 
 
 local utils = require "spine-lua.utils"
 local utils = require "spine-lua.utils"
 local AttachmentType = require "spine-lua.attachments.AttachmentType"
 local AttachmentType = require "spine-lua.attachments.AttachmentType"
+local math_floor = math.floor
+local math_abs = math.abs
+local math_signum = utils.signum
 
 
 local function zlen(array)
 local function zlen(array)
 	return #array + 1
 	return #array + 1
@@ -51,7 +54,7 @@ function Animation.new (name, timelines, duration)
 		duration = duration
 		duration = duration
 	}
 	}
 
 
-	function self:apply (skeleton, lastTime, time, loop, events)
+	function self:apply (skeleton, lastTime, time, loop, events, alpha, setupPose, mixingOut)
 		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
@@ -60,20 +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, 1)
-		end
-	end
-
-	function self:mix (skeleton, lastTime, time, loop, events, alpha)
-		if not skeleton then error("skeleton cannot be nil.", 2) end
-
-		if loop and duration > 0 then
-			time = time % self.duration
-			if lastTime > 0 then lastTime = lastTime % self.duration end
-		end
-
-		for i,timeline in ipairs(self.timelines) do
-			timeline:apply(skeleton, lastTime, time, events, alpha)
+			timeline:apply(skeleton, lastTime, time, events, alpha, setupPose, mixingOut)
 		end
 		end
 	end
 	end
 
 
@@ -122,6 +112,16 @@ local function linearSearch (values, target, step)
 	return -1
 	return -1
 end
 end
 
 
+Animation.TimelineType = {
+	rotate = 0, translate = 1, scale = 2, shear = 3,
+	attachment = 4, color = 5, deform = 6,
+	event = 7, drawOrder = 8,
+	ikConstraint = 9, transformConstraint = 10,
+	pathConstraintPosition = 11, pathConstraintSpacing = 12, pathConstraintMix = 13
+}
+local TimelineType = Animation.TimelineType
+local SHL_24 = 16777216
+
 Animation.CurveTimeline = {}
 Animation.CurveTimeline = {}
 function Animation.CurveTimeline.new (frameCount)
 function Animation.CurveTimeline.new (frameCount)
 	local LINEAR = 0
 	local LINEAR = 0
@@ -216,38 +216,44 @@ end
 
 
 Animation.RotateTimeline = {}
 Animation.RotateTimeline = {}
 Animation.RotateTimeline.ENTRIES = 2
 Animation.RotateTimeline.ENTRIES = 2
+Animation.RotateTimeline.PREV_TIME = -2
+Animation.RotateTimeline.PREV_ROTATION = -1
+Animation.RotateTimeline.ROTATION = 1
 function Animation.RotateTimeline.new (frameCount)
 function Animation.RotateTimeline.new (frameCount)
 	local ENTRIES = Animation.RotateTimeline.ENTRIES
 	local ENTRIES = Animation.RotateTimeline.ENTRIES
-	local PREV_TIME = -2
-	local PREV_ROTATION = -1
-	local ROTATION = 1
+	local PREV_TIME = Animation.RotateTimeline.PREV_TIME
+	local PREV_ROTATION = Animation.RotateTimeline.PREV_ROTATION
+	local ROTATION = Animation.RotateTimeline.ROTATION
 
 
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.boneIndex = -1
 	self.boneIndex = -1
 	self.frames = utils.newNumberArrayZero(frameCount * 2)
 	self.frames = utils.newNumberArrayZero(frameCount * 2)
 
 
+	function self:getPropertyId ()
+		return TimelineType.rotate * SHL_24 + self.boneIndex
+	end
+
 	function self:setFrame (frameIndex, time, degrees)
 	function self:setFrame (frameIndex, time, degrees)
 		frameIndex = frameIndex * 2
 		frameIndex = frameIndex * 2
 		self.frames[frameIndex] = time
 		self.frames[frameIndex] = time
 		self.frames[frameIndex + ROTATION] = degrees
 		self.frames[frameIndex + ROTATION] = degrees
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 
 
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			local amount = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] - bone.rotation
-			while amount > 180 do
-				amount = amount - 360
-			end
-			while amount < -180 do
-				amount = amount + 360
+			if setupPose 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
+				r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
+				bone.rotation = bone.rotation + r * alpha;
 			end
 			end
-			bone.rotation = bone.rotation + amount * alpha
-			return
+			return;
 		end
 		end
 
 
 		-- Interpolate between the last frame and the current frame.
 		-- Interpolate between the last frame and the current frame.
@@ -256,21 +262,17 @@ function Animation.RotateTimeline.new (frameCount)
 		local frameTime = frames[frame]
 		local frameTime = frames[frame]
 		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 amount = frames[frame + ROTATION] - prevRotation
-		while amount > 180 do
-			amount = amount - 360
-		end
-		while amount < -180 do
-			amount = amount + 360
-		end
-		amount = bone.data.rotation + (prevRotation + amount * percent) - bone.rotation
-		while amount > 180 do
-			amount = amount - 360
-		end
-		while amount < -180 do
-			amount = amount + 360
+		local r = frames[frame + ROTATION] - prevRotation
+		r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
+		r = prevRotation + r * percent
+		if setupPose 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
 		end
 		end
-		bone.rotation = bone.rotation + amount * alpha
 	end
 	end
 
 
 	return self
 	return self
@@ -289,6 +291,10 @@ function Animation.TranslateTimeline.new (frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.boneIndex = -1
 	self.boneIndex = -1
+	
+	function self:getPropertyId ()
+		return TimelineType.translate * SHL_24 + self.boneIndex
+	end
 
 
 	function self:setFrame (frameIndex, time, x, y)
 	function self:setFrame (frameIndex, time, x, y)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
@@ -297,27 +303,36 @@ 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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 
 
-		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			bone.x = bone.x + (bone.data.x + frames[zlen(frames) + PREV_X] - bone.x) * alpha
-			bone.y = bone.y + (bone.data.y + frames[zlen(frames) + PREV_Y] - bone.y) * alpha
-			return
-		end
-
-		-- Interpolate between the last frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local prevX = frames[frame + PREV_X]
-		local prevY = frames[frame + PREV_Y]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
+		local x = 0
+		local y = 0
+		if time >= frames[zlen(frames) - ENTRIES] then -- // Time is after last frame.
+			x = frames[zlen(frames) + PREV_X];
+			y = frames[zlen(frames) + PREV_Y];
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			x = frames[frame + PREV_X]
+			y = frames[frame + PREV_Y]
+			local frameTime = frames[frame]
+			local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
+				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
 
 
-		bone.x = bone.x + (bone.data.x + prevX + (frames[frame + X] - prevX) * percent - bone.x) * alpha
-		bone.y = bone.y + (bone.data.y + prevY + (frames[frame + Y] - prevY) * percent - bone.y) * alpha
+			x = x + (frames[frame + X] - x) * percent
+			y = y + (frames[frame + Y] - y) * percent
+		end
+		if setupPose then
+			bone.x = bone.data.x + x * alpha
+			bone.y = bone.data.y + y * alpha
+		else
+			bone.x = bone.x + (bone.data.x + x - bone.x) * alpha
+			bone.y = bone.y + (bone.data.y + y - bone.y) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -334,29 +349,58 @@ function Animation.ScaleTimeline.new (frameCount)
 	local Y = 2
 	local Y = 2
 
 
 	local self = Animation.TranslateTimeline.new(frameCount)
 	local self = Animation.TranslateTimeline.new(frameCount)
+	
+	function self:getPropertyId ()
+		return TimelineType.scale * SHL_24 + self.boneIndex
+	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 
 
+		local x = 0
+		local y = 0
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			bone.scaleX = bone.scaleX + (bone.data.scaleX * frames[zlen(frames) + PREV_X] - bone.scaleX) * alpha
-			bone.scaleY = bone.scaleY + (bone.data.scaleY * frames[zlen(frames) + PREV_Y] - bone.scaleY) * alpha
-			return
-		end
-
-		-- Interpolate between the last frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local prevX = frames[frame + PREV_X]
-		local prevY = frames[frame + PREV_Y]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
+			x = frames[zlen(frames) + PREV_X] * bone.data.scaleX
+			y = frames[zlen(frames) + PREV_Y] * bone.data.scaleY
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			x = frames[frame + PREV_X]
+			y = frames[frame + PREV_Y]
+			local frameTime = frames[frame]
+			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))
 
 
-		bone.scaleX = bone.scaleX + (bone.data.scaleX * (prevX + (frames[frame + X] - prevX) * percent) - bone.scaleX) * alpha
-		bone.scaleY = bone.scaleY + (bone.data.scaleY * (prevY + (frames[frame + Y] - prevY) * percent) - bone.scaleY) * alpha
+			x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX
+			y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY
+		end
+		if alpha == 1 then
+			bone.scaleX = x
+			bone.scaleY = y
+		else
+			local bx = 0
+			local by = 0
+			if setupPose 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 mixingOut then
+				x = math_abs(x) * math_signum(bx)
+				y = math_abs(y) * math_signum(by)
+			else
+				bx = math_abs(bx) * math_signum(x)
+				by = math_abs(by) * math_signum(y)
+			end
+			bone.scaleX = bx + (x - bx) * alpha
+			bone.scaleY = by + (y - by) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -373,29 +417,41 @@ function Animation.ShearTimeline.new (frameCount)
 	local Y = 2
 	local Y = 2
 
 
 	local self = Animation.TranslateTimeline.new(frameCount)
 	local self = Animation.TranslateTimeline.new(frameCount)
+	
+	function self:getPropertyId ()
+		return TimelineType.shear * SHL_24 + self.boneIndex
+	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local bone = skeleton.bones[self.boneIndex]
 		local bone = skeleton.bones[self.boneIndex]
 
 
-		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			bone.shearX = bone.shearX + (bone.data.shearX * frames[zlen(frames) + PREV_X] - bone.shearX) * alpha
-			bone.shearY = bone.shearY + (bone.data.shearY * frames[zlen(frames) + PREV_Y] - bone.shearY) * alpha
-			return
-		end
-
-		-- Interpolate between the last frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local prevX = frames[frame + PREV_X]
-		local prevY = frames[frame + PREV_Y]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
+		local x = 0
+		local y = 0
+		if time >= frames[zlen(frames) - ENTRIES] then -- // Time is after last frame.
+			x = frames[zlen(frames) + PREV_X]
+			y = frames[zlen(frames) + PREV_Y]
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			x = frames[frame + PREV_X]
+			y = frames[frame + PREV_Y]
+			local frameTime = frames[frame]
+			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))
 
 
-		bone.shearX = bone.shearX + (bone.data.shearX + (prevX + (frames[frame + X] - prevX) * percent) - bone.shearX) * alpha
-		bone.shearY = bone.shearY + (bone.data.shearY + (prevY + (frames[frame + Y] - prevY) * percent) - bone.shearY) * alpha
+			x = x + (frames[frame + X] - x) * percent
+			y = y + (frames[frame + Y] - y) * percent
+		end
+		if setupPose then
+			bone.shearX = bone.data.shearX + x * alpha
+			bone.shearY = bone.data.shearY + y * alpha
+		else
+			bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha
+			bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -418,6 +474,10 @@ function Animation.ColorTimeline.new (frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.slotIndex = -1
 	self.slotIndex = -1
+	
+	function self:getPropertyId ()
+		return TimelineType.color * SHL_24 + self.slotIndex
+	end
 
 
 	function self:setFrame (frameIndex, time, r, g, b, a)
 	function self:setFrame (frameIndex, time, r, g, b, a)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
@@ -428,7 +488,7 @@ 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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
@@ -455,11 +515,13 @@ function Animation.ColorTimeline.new (frameCount)
 			b = b + (frames[frame + B] - b) * percent
 			b = b + (frames[frame + B] - b) * percent
 			a = a + (frames[frame + A] - a) * percent
 			a = a + (frames[frame + A] - a) * percent
 		end
 		end
-		local color = skeleton.slots[self.slotIndex].color
-		if alpha < 1 then
-			color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha)
+		local slot = skeleton.slots[slotIndex]
+		if alpha == 1 then
+			slot.color:set(r, g, b, a)
 		else
 		else
-			color:set(r, g, b, a)
+			local color = slot.color
+			if setupPose 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)
 		end
 		end
 	end
 	end
 
 
@@ -471,7 +533,7 @@ function Animation.AttachmentTimeline.new (frameCount)
 	local self = {
 	local self = {
 		frames = utils.newNumberArrayZero(frameCount), -- time, ...
 		frames = utils.newNumberArrayZero(frameCount), -- time, ...
 		attachmentNames = {},
 		attachmentNames = {},
-		slotName = nil
+		slotIndex = -1
 	}
 	}
 
 
 	function self:getFrameCount ()
 	function self:getFrameCount ()
@@ -482,8 +544,25 @@ function Animation.AttachmentTimeline.new (frameCount)
 		self.frames[frameIndex] = time
 		self.frames[frameIndex] = time
 		self.attachmentNames[frameIndex] = attachmentName
 		self.attachmentNames[frameIndex] = attachmentName
 	end
 	end
+	
+	function self:getPropertyId ()
+		return Timeline.attachment * SHL_24 + self.slotIndex
+	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
+		local slot
+		local attachmentName
+		if mixingOut and setupPose then
+			slot = skeleton.slots[self.slotIndex]
+			attachmentName = slot.data.attachmentName
+			if not attachmentName then
+				slot:setAttachment(nil)
+			else
+				skeleton:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
+			end
+			return;
+		end
+		
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end
 		if time < frames[0] then return end
 
 
@@ -494,16 +573,134 @@ function Animation.AttachmentTimeline.new (frameCount)
 			frameIndex = binarySearch(frames, time, 1) - 1
 			frameIndex = binarySearch(frames, time, 1) - 1
 		end
 		end
 
 
-		local attachmentName = self.attachmentNames[frameIndex]
-		local slot = skeleton.slotsByName[self.slotName]
-		if attachmentName then
-			if not slot.attachment then
-				slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
-			elseif slot.attachment.name ~= attachmentName then
-				slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
+		attachmentName = self.attachmentNames[frameIndex]
+		if not attachmentName then
+			skeleton.slots[self.slotIndex]:setAttachment(nil)
+		else
+			skeleton.slots[self.slotIndex]:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
+		end
+	end
+
+	return self
+end
+
+Animation.DeformTimeline = {}
+function Animation.DeformTimeline.new (frameCount)
+	local self = Animation.CurveTimeline.new(frameCount)
+	self.frames = utils.newNumberArrayZero(frameCount)
+	self.frameVertices = utils.newNumberArrayZero(frameCount)
+	self.slotIndex = -1
+	self.attachment = nil
+
+	function self:getPropertyId ()
+		return TimelineType.deform * SHL_24 + self.slotIndex
+	end
+
+	function self:setFrame (frameIndex, time, vertices)
+		self.frames[frameIndex] = time
+		self.frameVertices[frameIndex] = vertices
+	end
+
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
+		local slot = skeleton.slots[self.slotIndex]
+		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
+		if not slotAttachment:applyDeform(self.attachment) then return end
+
+		local frames = self.frames
+		if time < frames[0] then return end -- Time is before first frame.
+
+		local frameVertices = self.frameVertices
+		local vertexCount = #(frameVertices[0])
+
+		local verticesArray = slot.attachmentVertices
+		if (#verticesArray ~= vertexCount) then alpha = 1 end -- Don't mix from uninitialized slot vertices.
+		local vertices = utils.setArraySize(verticesArray, vertexCount)
+
+		if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
+			local lastVertices = frameVertices[zlen(frames) - 1]
+			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 setupPose 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
+			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
+				end
+			end
+			return;
+		end
+
+		-- Interpolate between the previous frame and the current frame.
+		local frame = binarySearch(frames, time, 1)
+		local prevVertices = frameVertices[frame - 1]
+		local nextVertices = frameVertices[frame]
+		local frameTime = frames[frame]
+		local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
+
+		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 setupPose 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
 			end
 		else
 		else
-			slot:setAttachment(nil)
+			-- 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
+			end
 		end
 		end
 	end
 	end
 
 
@@ -516,6 +713,10 @@ function Animation.EventTimeline.new (frameCount)
 		frames = utils.newNumberArrayZero(frameCount),
 		frames = utils.newNumberArrayZero(frameCount),
 		events = {}
 		events = {}
 	}
 	}
+	
+	function self:getPropertyId ()
+		return Timeline.event * SHL_24
+	end
 
 
 	function self:getFrameCount ()
 	function self:getFrameCount ()
 		return zlen(self.frames)
 		return zlen(self.frames)
@@ -527,14 +728,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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		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)
+			self:apply(skeleton, lastTime, 999999, firedEvents, alpha, setupPose, mixingOut)
 			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
@@ -568,6 +769,10 @@ function Animation.DrawOrderTimeline.new (frameCount)
 		frames = utils.newNumberArrayZero(frameCount),
 		frames = utils.newNumberArrayZero(frameCount),
 		drawOrders = {}
 		drawOrders = {}
 	}
 	}
+	
+	function self:getPropertyId ()
+		return Timeline.drawOrder * SHL_24
+	end
 
 
 	function self:getFrameCount ()
 	function self:getFrameCount ()
 		return zlen(self.frames)
 		return zlen(self.frames)
@@ -578,7 +783,15 @@ function Animation.DrawOrderTimeline.new (frameCount)
 		self.drawOrders[frameIndex] = drawOrder
 		self.drawOrders[frameIndex] = drawOrder
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
+		local drawOrder = skeleton.drawOrder
+		local slots = skeleton.slots
+		if mixingOut and setupPose then
+			for i,slot in ipairs(slots) do
+				drawOrder[i] = slots[i]
+			end
+			return;
+		end
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
@@ -589,8 +802,6 @@ function Animation.DrawOrderTimeline.new (frameCount)
 			frame = binarySearch1(frames, time) - 1
 			frame = binarySearch1(frames, time) - 1
 		end
 		end
 
 
-		local drawOrder = skeleton.drawOrder
-		local slots = skeleton.slots
 		local drawOrderToSetupIndex = self.drawOrders[frame]
 		local drawOrderToSetupIndex = self.drawOrders[frame]
 		if not drawOrderToSetupIndex then
 		if not drawOrderToSetupIndex then
 			for i,slot in ipairs(slots) do
 			for i,slot in ipairs(slots) do
@@ -606,81 +817,6 @@ function Animation.DrawOrderTimeline.new (frameCount)
 	return self
 	return self
 end
 end
 
 
-Animation.DeformTimeline = {}
-function Animation.DeformTimeline.new (frameCount)
-	local self = Animation.CurveTimeline.new(frameCount)
-	self.frames = utils.newNumberArrayZero(frameCount)
-	self.frameVertices = utils.newNumberArrayZero(frameCount)
-	self.slotIndex = -1
-	self.attachment = nil
-
-	function self:setFrame (frameIndex, time, vertices)
-		self.frames[frameIndex] = time
-		self.frameVertices[frameIndex] = vertices
-	end
-
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
-		local slot = skeleton.slots[self.slotIndex]
-		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) then return end
-		if not slotAttachment:applyDeform(self.attachment) then return end
-
-		local frames = self.frames
-		if time < frames[0] then return end -- Time is before first frame.
-
-		local frameVertices = self.frameVertices
-		local vertexCount = #(frameVertices[0])
-
-		local verticesArray = slot.attachmentVertices
-		if (#verticesArray ~= vertexCount) then alpha = 1 end -- Don't mix from uninitialized slot vertices.
-		local vertices = utils.setArraySize(verticesArray, vertexCount)
-
-		if time >= frames[zlen(frames) - 1] then
-			local lastVertices = frameVertices[zlen(frames) - 1]
-			if alpha < 1 then
-				local i = 1
-				while i <= vertexCount do
-					vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha
-					i = i + 1
-				end
-			else
-				local i = 1
-				while i <= vertexCount do
-					vertices[i] = lastVertices[i]
-					i = i + 1
-				end
-			end
-			return;
-		end
-
-		-- Interpolate between the previous frame and the current frame.
-		local frame = binarySearch(frames, time, 1)
-		local prevVertices = frameVertices[frame - 1]
-		local nextVertices = frameVertices[frame]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
-
-		if alpha < 1 then
-			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
-			end
-		else
-			local i = 1
-			while i <= vertexCount do
-				local prev = prevVertices[i]
-				vertices[i] = prev + (nextVertices[i] - prev) * percent
-				i = i + 1
-			end
-		end
-	end
-
-	return self
-end
-
 Animation.IkConstraintTimeline = {}
 Animation.IkConstraintTimeline = {}
 Animation.IkConstraintTimeline.ENTRIES = 3
 Animation.IkConstraintTimeline.ENTRIES = 3
 function Animation.IkConstraintTimeline.new (frameCount)
 function Animation.IkConstraintTimeline.new (frameCount)
@@ -694,6 +830,10 @@ function Animation.IkConstraintTimeline.new (frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, bendDirection, ...
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, bendDirection, ...
 	self.ikConstraintIndex = -1
 	self.ikConstraintIndex = -1
+	
+	function self:getPropertyId ()
+		return TimelineType.ikConstraint * SHL_24 + self.ikConstraintIndex
+	end
 
 
 	function self:setFrame (frameIndex, time, mix, bendDirection)
 	function self:setFrame (frameIndex, time, mix, bendDirection)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
@@ -702,15 +842,24 @@ 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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
 		local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
 
 
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			constraint.mix = constraint.mix + (frames[zlen(frames) + PREV_MIX] - constraint.mix) * alpha
-			constraint.bendDirection = frames[zlen(frames) + PREV_BEND_DIRECTION]
+			if setupPose then
+				constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
+				if mixingOut then 
+					constraint.bendDirection = constraint.data.bendDirection
+				else
+					constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]);
+				end
+			else
+				constraint.mix = constraint.mix + (frames[frames.length + PREV_MIX] - constraint.mix) * alpha;
+				if not mixingOut then constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]) end
+			end
 			return
 			return
 		end
 		end
 
 
@@ -721,8 +870,17 @@ 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))
 
 
-		constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha
-			constraint.bendDirection = math.floor(frames[frame + PREV_BEND_DIRECTION])
+		if setupPose then
+			constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
+			if mixingOut then
+				constraint.bendDirection = constraint.data.bendDirection
+			else
+				constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
+			end
+		else
+			constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
+			if not mixingOut then constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION]) end
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -745,6 +903,10 @@ function Animation.TransformConstraintTimeline.new (frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.transformConstraintIndex = -1
 	self.transformConstraintIndex = -1
+	
+	function self:getPropertyId ()
+		return TimelineType.transformConstraint * SHL_24 + self.transformConstraintIndex
+	end
 
 
 	function self:setFrame (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix)
 	function self:setFrame (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
@@ -755,34 +917,50 @@ 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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if time < frames[0] then return end -- Time is before first frame.
 		if time < frames[0] then return end -- Time is before first frame.
 
 
 		local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
 		local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
 
 
+		local rotate = 0
+		local translate = 0
+		local scale = 0
+		local shear = 0
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-				local i = zlen(frames)
-				constraint.rotateMix = constraintMix.rotateMix + (frames[i + PREV_ROTATE] - constraint.rotateMix) * alpha
-				constraint.translateMix = constraintMix.translateMix + (frames[i + PREV_TRANSLATE] - constraint.translateMix) * alpha
-				constraint.scaleMix = constraintMix.scaleMix + (frames[i + PREV_SCALE] - constraint.scaleMix) * alpha
-				constraint.shearMix = constraintMix.shearMix + (frames[i + PREV_SHEAR] - constraint.shearMix) * alpha
-			return
-		end
-
-		-- Interpolate between the last frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
+			local i = zlen(frames.length)
+			rotate = frames[i + PREV_ROTATE]
+			translate = frames[i + PREV_TRANSLATE]
+			scale = frames[i + PREV_SCALE]
+			shear = frames[i + PREV_SHEAR]
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			rotate = frames[frame + PREV_ROTATE]
+			translate = frames[frame + PREV_TRANSLATE]
+			scale = frames[frame + PREV_SCALE]
+			shear = frames[frame + PREV_SHEAR]
+			local frameTime = frames[frame]
+			local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
+				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
 
 
-		local rotate = frames[frame + PREV_ROTATE]
-		local translate = frames[frame + PREV_TRANSLATE]
-		local scale = frames[frame + PREV_SCALE]
-		local shear = frames[frame + PREV_SHEAR]
-		constraint.rotateMix = constraint.rotateMix + (rotate + (frames[frame + ROTATE] - rotate) * percent - constraint.rotateMix) * alpha
-		constraint.translateMix = constraint.translateMix + (translate + (frames[frame + TRANSLATE] - translate) * percent - constraint.translateMix) * alpha
-		constraint.scaleMix = constraint.scaleMix + (scale + (frames[frame + SCALE] - scale) * percent - constraint.scaleMix) * alpha
-		constraint.shearMix = constraint.shearMix + (shear + (frames[frame + SHEAR] - shear) * percent - constraint.shearMix) * alpha
+			rotate = rotate + (frames[frame + ROTATE] - rotate) * percent
+			translate = translate + (frames[frame + TRANSLATE] - translate) * percent
+			scale = scale + (frames[frame + SCALE] - scale) * percent
+			shear = shear + (frames[frame + SHEAR] - shear) * percent
+		end
+		if setupPose then
+			local data = constraint.data
+			constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha
+			constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha
+			constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha
+			constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha
+		else
+			constraint.rotateMix = constraint.rotateMix + (rotate - constraint.rotateMix) * alpha
+			constraint.translateMix = constraint.translateMix + (translate - constraint.translateMix) * alpha
+			constraint.scaleMix = constraint.scaleMix + (scale - constraint.scaleMix) * alpha
+			constraint.shearMix = constraint.shearMix + (shear - constraint.shearMix) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -800,31 +978,40 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.pathConstraintIndex = -1
 	self.pathConstraintIndex = -1
 
 
+	function self:getPropertyId ()
+		return TimelineType.pathConstraintPosition * SHL_24 + self.pathConstraintIndex
+	end
+
 	function self:setFrame (frameIndex, time, value)
 	function self:setFrame (frameIndex, time, value)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
 		self.frames[frameIndex] = time
 		self.frames[frameIndex] = time
 		self.frames[frameIndex + VALUE] = value
 		self.frames[frameIndex + VALUE] = value
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if (time < frames[0]) then return end -- Time is before first frame.
 		if (time < frames[0]) then return end -- Time is before first frame.
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 
 
+		local position = 0
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			local i = zlen(frames)
-			constraint.position = constraint.position + (frames[i + PREV_VALUE] - constraint.position) * alpha
-			return
-		end
-
-		-- Interpolate between the previous frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local position = frames[frame + PREV_VALUE]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
+			position = frames[zlen(frames) + PREV_VALUE]
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			position = frames[frame + PREV_VALUE]
+			local frameTime = frames[frame]
+			local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
+				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 
 
-		constraint.position = constraint.position + (position + (frames[frame + VALUE] - position) * percent - constraint.position) * alpha
+			position = position + (frames[frame + VALUE] - position) * percent
+		end
+		if setupPose then
+			constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
+		else
+			constraint.position = constraint.position + (position - constraint.position) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -842,31 +1029,41 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.pathConstraintIndex = -1
 	self.pathConstraintIndex = -1
 
 
+	function self:getPropertyId ()
+		return TimelineType.pathConstraintSpacing * SHL_24 + self.pathConstraintIndex
+	end
+
 	function self:setFrame (frameIndex, time, value)
 	function self:setFrame (frameIndex, time, value)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
 		self.frames[frameIndex] = time
 		self.frames[frameIndex] = time
 		self.frames[frameIndex + VALUE] = value
 		self.frames[frameIndex + VALUE] = value
 	end
 	end
 
 
-	function self:apply (skeleton, lastTime, time, firedEvents, alpha)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if (time < frames[0]) then return end -- Time is before first frame.
 		if (time < frames[0]) then return end -- Time is before first frame.
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 
 
+		local spacing = 0
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			local i = zlen(frames)
-			constraint.spacing = constraint.spacing + (frames[i + PREV_VALUE] - constraint.spacing) * alpha
-			return
-		end
+			spacing = frames[zlen(frames) + PREV_VALUE]
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			spacing = frames[frame + PREV_VALUE]
+			local frameTime = frames[frame]
+			local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
+				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 
 
-		-- Interpolate between the previous frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local spacing = frames[frame + PREV_VALUE]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
+			spacing = spacing + (frames[frame + VALUE] - spacing) * percent
+		end
 
 
-		constraint.spacing = constraint.spacing + (spacing + (frames[frame + VALUE] - spacing) * percent - constraint.spacing) * alpha
+		if setupPose then
+			constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
+		else
+			constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self
@@ -885,6 +1082,10 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	local self = Animation.CurveTimeline.new(frameCount)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
 	self.pathConstraintIndex = -1
 	self.pathConstraintIndex = -1
+	
+	function self:getPropertyId ()
+		return TimelineType.pathConstraintMix * SHL_24 + self.pathConstraintIndex
+	end
 
 
 	function self:setFrame (frameIndex, time, rotateMix, translateMix)
 	function self:setFrame (frameIndex, time, rotateMix, translateMix)
 		frameIndex = frameIndex * ENTRIES
 		frameIndex = frameIndex * ENTRIES
@@ -893,28 +1094,37 @@ 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)
+	function self:apply (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut)
 		local frames = self.frames
 		local frames = self.frames
 		if (time < frames[0]) then return end -- Time is before first frame.
 		if (time < frames[0]) then return end -- Time is before first frame.
 
 
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 		local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
 
 
+		local rotate = 0
+		local translate = 0
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
 		if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
-			local i = zlen(frames)
-			constraint.rotateMix = constraint.rotateMix + (frames[i + PREV_ROTATE] - constraint.rotateMix) * alpha
-			constraint.translateMix = constraint.translateMix + (frames[i + PREV_TRANSLATE] - constraint.translateMix) * alpha
-			return
-		end
+			rotate = frames[zlen(frames) + PREV_ROTATE]
+			translate = frames[zlen(frames) + PREV_TRANSLATE]
+		else
+			-- Interpolate between the previous frame and the current frame.
+			local frame = binarySearch(frames, time, ENTRIES)
+			rotate = frames[frame + PREV_ROTATE]
+			translate = frames[frame + PREV_TRANSLATE]
+			local frameTime = frames[frame]
+			local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
+				1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
 
 
-		-- Interpolate between the previous frame and the current frame.
-		local frame = binarySearch(frames, time, ENTRIES)
-		local rotate = frames[frame + PREV_ROTATE]
-		local translate = frames[frame + PREV_TRANSLATE]
-		local frameTime = frames[frame]
-		local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
+			rotate = rotate + (frames[frame + ROTATE] - rotate) * percent
+			translate = translate + (frames[frame + TRANSLATE] - translate) * percent
+		end
 
 
-		constraint.rotateMix = constraint.rotateMix + (rotate + (frames[frame + ROTATE] - rotate) * percent - constraint.rotateMix) * alpha
-		constraint.translateMix = constraint.translateMix + (translate + (frames[frame + TRANSLATE] - translate) * percent - constraint.translateMix) * alpha
+		if setupPose then
+			constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha
+			constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha
+		else
+			constraint.rotateMix = constraint.rotateMix + (rotate - constraint.rotateMix) * alpha
+			constraint.translateMix = constraint.translateMix + (translate - constraint.translateMix) * alpha
+		end
 	end
 	end
 
 
 	return self
 	return self

+ 1 - 1
spine-lua/SkeletonJson.lua

@@ -457,7 +457,7 @@ function SkeletonJson.new (attachmentLoader)
 
 
 					elseif timelineName == "attachment" then
 					elseif timelineName == "attachment" then
 						local timeline = Animation.AttachmentTimeline.new(#values)
 						local timeline = Animation.AttachmentTimeline.new(#values)
-						timeline.slotName = slotName
+						timeline.slotIndex = slotIndex
 
 
 						local frameIndex = 0
 						local frameIndex = 0
 						for i,valueMap in ipairs(values) do
 						for i,valueMap in ipairs(values) do