Sfoglia il codice sorgente

[lua] Ported changes to AnimationState and Animation, see #1303. Also ported fix for #1352.

badlogic 6 anni fa
parent
commit
bdfd390dae
2 ha cambiato i file con 75 aggiunte e 10 eliminazioni
  1. 57 10
      spine-lua/AnimationState.lua
  2. 18 0
      spine-lua/utils.lua

+ 57 - 10
spine-lua/AnimationState.lua

@@ -41,6 +41,9 @@ local math_signum = utils.signum
 local math_floor = math.floor
 local math_ceil = math.ceil
 local math_mod = utils.mod
+local testBit = utils.testBit
+local setBit = utils.setBit
+local clearBit = utils.clearBit
 
 local function zlen(array)
 	return #array + 1
@@ -50,7 +53,8 @@ local EMPTY_ANIMATION = Animation.new("<empty>", {}, 0)
 local SUBSEQUENT = 0
 local FIRST = 1
 local HOLD = 2
-local HOLD_MIX = 3;
+local HOLD_MIX = 3
+local NOT_LAST = 4
 
 local EventType = {
 	start = 0,
@@ -357,7 +361,7 @@ function AnimationState:apply (skeleton)
 
 				for ii,timeline in ipairs(timelines) do
 					local timelineBlend = MixBlend.setup
-					if timelineMode[ii] == SUBSEQUENT then timelineBlend = blend end
+					if clearBit(timelineMode[ii], NOT_LAST) == SUBSEQUENT then timelineBlend = blend end
 
 					if timeline.type == Animation.TimelineType.rotate then
 						self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii * 2,
@@ -421,15 +425,21 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
       local direction = MixDirection.out;
 			local timelineBlend = MixBlend.setup
 			local alpha = 0
-			if timelineMode[i] == SUBSEQUENT then
-				if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
+			if clearBit(timelineMode[i], NOT_LAST) == SUBSEQUENT then
+				if not attachments and timeline.type == Animation.TimelineType.attachment then
+					if testBit(timelineMode[i], NOT_LAST) then 
+						skipSubsequent = true
+					else
+						blend = MixBlend.setup
+					end
+				end
 				if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
 				timelineBlend = blend
 				alpha = alphaMix
-			elseif timelineMode[i] == FIRST then
+			elseif clearBit(timelineMode[i], NOT_LAST) == FIRST then
 				timelineBlend = MixBlend.setup
 				alpha = alphaMix
-			elseif timelineMode[i] == HOLD then
+			elseif clearBit(timelineMode[i], NOT_LAST) == HOLD then
 				timelineBlend = MixBlend.setup
 				alpha = alphaHold
 			else
@@ -445,7 +455,7 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
 				else
           if timelineBlend == MixBlend.setup then
             if timeline.type == Animation.TimelineType.attachment then
-              if attachments then direction = MixDirection._in end
+              if attachments or testBit(timelineMode[i], NOT_LAST) then direction = MixDirection._in end
             elseif timeline.type == Animation.TimelineType.drawOrder then
               if drawOrder then direction = MixDirection._in end
             end
@@ -803,7 +813,10 @@ function AnimationState:_animationsChanged ()
 
 	self.propertyIDs = {}
 
+	local highestIndex = -1
 	for i, entry in pairs(self.tracks) do
+		if i > highestIndex then highestIndex = i end
+		
 		if entry then
 			while entry.mixingFrom do
 				entry = entry.mixingFrom
@@ -811,15 +824,45 @@ function AnimationState:_animationsChanged ()
 
 			repeat
 				if (entry.mixingTo == nil or entry.mixBlend ~= MixBlend.add) then
-					self:setTimelineModes(entry)
+					self:computeHold(entry)
 				end
 				entry = entry.mixingTo
 			until (entry == nil)
 		end
 	end
+	
+	self.propertyIDs = {}
+	for i = highestIndex, 0, -1 do
+		entry = self.tracks[i]
+		while entry do
+			self:computeNotLast(entry)
+			entry = entry.mixingFrom
+		end
+	end
+end
+
+function AnimationState:computeNotLast(entry)
+	local timelines = entry.animation.timelines
+	local timelinesCount = #entry.animation.timelines
+	local timelineMode = entry.timelineMode
+	local propertyIDs = self.propertyIDs
+	
+	local i = 1
+	while i <= timelinesCount do
+		local timeline = timelines[i]
+		if (timeline.type == Animation.TimelineType.attachment) then
+			local slotIndex = timeline.slotIndex
+			if not (propertyIDs[slotIndex] == nil) then
+				timelineMode[i] = setBit(timelineMode[i], NOT_LAST)
+			else
+				propertyIDs[slotIndex] = true
+			end
+		end
+		i = i + 1
+	end
 end
 
-function AnimationState:setTimelineModes(entry)
+function AnimationState:computeHold(entry)
 	local to = entry.mixingTo
 	local timelines = entry.animation.timelines
 	local timelinesCount = #entry.animation.timelines
@@ -847,7 +890,11 @@ function AnimationState:setTimelineModes(entry)
 			timelineMode[i] = SUBSEQUENT
 		else
 			propertyIDs[id] = id
-			if to == nil or not self:hasTimeline(to, id) then
+			local timeline = timelines[i]
+			if to == nil or timeline.type == Animation.TimelineType.attachment 
+				or timeline.type == Animation.TimelineType.drawOrder 
+				or timeline.type == Animation.TimelineType.event 
+				or not self:hasTimeline(to, id) then
 				timelineMode[i] = FIRST
 			else
 				local next = to.mixingTo

+ 18 - 0
spine-lua/utils.lua

@@ -166,4 +166,22 @@ function utils.randomTriangularWith(min, max, mode)
 	return max - math_sqrt((1 - u) * d * (max - mode))
 end
 
+function utils.testBit(value, bit)
+  return value % (2 * bit) >= bit
+end
+
+function utils.setBit(value, bit)
+  if value % (2 * bit) >= bit then
+    return value
+  end
+  return value + bit
+end
+
+function utils.clearBit(value, bit)
+  if value % (2 * bit) >= bit then
+    return value - bit
+  end
+  return value
+end
+
 return utils