mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
Merge branch '3.8' into 3.9-beta
This commit is contained in:
commit
6b1e87e6bc
@ -775,16 +775,22 @@ function Animation.AttachmentTimeline.new (frameCount)
|
||||
return TimelineType.attachment * SHL_24 + self.slotIndex
|
||||
end
|
||||
|
||||
function self:setAttachment(skeleton, slot, attachmentName)
|
||||
attachmentName = slot.data.attachmentName
|
||||
if not attachmentName then
|
||||
slot:setAttachment(nil)
|
||||
else
|
||||
slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
|
||||
end
|
||||
end
|
||||
|
||||
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
|
||||
local slot = skeleton.slots[self.slotIndex]
|
||||
if not slot.bone.active then return end
|
||||
local attachmentName
|
||||
if direction == MixDirection.out and blend == MixBlend.setup then
|
||||
attachmentName = slot.data.attachmentName
|
||||
if not attachmentName then
|
||||
slot:setAttachment(nil)
|
||||
else
|
||||
slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
|
||||
if direction == MixDirection.out then
|
||||
if blend == MixBlend.setup then
|
||||
self:setAttachment(skeleton, slot, slot.data.attachmentName)
|
||||
end
|
||||
return;
|
||||
end
|
||||
@ -792,12 +798,7 @@ function Animation.AttachmentTimeline.new (frameCount)
|
||||
local frames = self.frames
|
||||
if time < frames[0] then
|
||||
if blend == MixBlend.setup or blend == MixBlend.first then
|
||||
attachmentName = slot.data.attachmentName
|
||||
if not attachmentName then
|
||||
slot:setAttachment(nil)
|
||||
else
|
||||
slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
|
||||
end
|
||||
self:setAttachment(skeleton, slot, slot.data.attachmentName)
|
||||
end
|
||||
return
|
||||
end
|
||||
@ -1150,9 +1151,11 @@ function Animation.DrawOrderTimeline.new (frameCount)
|
||||
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
|
||||
local drawOrder = skeleton.drawOrder
|
||||
local slots = skeleton.slots
|
||||
if direction == MixDirection.out and blend == MixBlend.setup then
|
||||
for i,slot in ipairs(slots) do
|
||||
drawOrder[i] = slots[i]
|
||||
if direction == MixDirection.out then
|
||||
if blend == MixBlend.setup then
|
||||
for i,slot in ipairs(slots) do
|
||||
drawOrder[i] = slots[i]
|
||||
end
|
||||
end
|
||||
return;
|
||||
end
|
||||
|
||||
@ -54,7 +54,9 @@ local SUBSEQUENT = 0
|
||||
local FIRST = 1
|
||||
local HOLD = 2
|
||||
local HOLD_MIX = 3
|
||||
local NOT_LAST = 4
|
||||
|
||||
local SETUP = 1
|
||||
local CURRENT = 2
|
||||
|
||||
local EventType = {
|
||||
start = 0,
|
||||
@ -214,7 +216,8 @@ function AnimationState.new (data)
|
||||
propertyIDs = {},
|
||||
animationsChanged = false,
|
||||
timeScale = 1,
|
||||
mixingTo = {}
|
||||
mixingTo = {},
|
||||
unkeyedState = 0
|
||||
}
|
||||
self.queue = EventQueue.new(self)
|
||||
setmetatable(self, AnimationState)
|
||||
@ -358,7 +361,11 @@ function AnimationState:apply (skeleton)
|
||||
local timelines = current.animation.timelines
|
||||
if (i == 0 and mix == 1) or blend == MixBlend.add then
|
||||
for i,timeline in ipairs(timelines) do
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, mix, blend, MixDirection._in)
|
||||
if timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true)
|
||||
else
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, mix, blend, MixDirection._in)
|
||||
end
|
||||
end
|
||||
else
|
||||
local timelineMode = current.timelineMode
|
||||
@ -367,11 +374,13 @@ function AnimationState:apply (skeleton)
|
||||
|
||||
for ii,timeline in ipairs(timelines) do
|
||||
local timelineBlend = MixBlend.setup
|
||||
if clearBit(timelineMode[ii], NOT_LAST) == SUBSEQUENT then timelineBlend = blend end
|
||||
if timelineMode[ii] == SUBSEQUENT then timelineBlend = blend end
|
||||
|
||||
if timeline.type == Animation.TimelineType.rotate then
|
||||
self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii * 2,
|
||||
firstFrame)
|
||||
elseif timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(skeleton, animationTime, timelineBlend, true)
|
||||
else
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, mix, timelineBlend, MixDirection._in)
|
||||
end
|
||||
@ -386,6 +395,24 @@ function AnimationState:apply (skeleton)
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- Set slots attachments to the setup pose, if needed. This occurs if an animation that is mixing out sets attachments so
|
||||
-- subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or
|
||||
-- the time is before the first key).
|
||||
local setupState = self.unkeyedState + SETUP
|
||||
local slots = skeleton.slots;
|
||||
for _, slot in ipairs(slots) do
|
||||
if slot.attachmentState == setupState then
|
||||
local attachmentName = slot.data.attachmentName
|
||||
if attachmentName == nil then
|
||||
slot.attachment = nil
|
||||
else
|
||||
slot.attachment = skeleton:getAttachmentByIndex(slot.data.index, attachmentName)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.unkeyedState = self.unkeyedState + 2; -- Increasing after each use avoids the need to reset attachmentState for every slot.
|
||||
|
||||
|
||||
queue:drain()
|
||||
return applied
|
||||
end
|
||||
@ -432,21 +459,14 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
local direction = MixDirection.out;
|
||||
local timelineBlend = MixBlend.setup
|
||||
local alpha = 0
|
||||
if clearBit(timelineMode[i], NOT_LAST) == SUBSEQUENT then
|
||||
timelineBlend = blend
|
||||
if not attachments and timeline.type == Animation.TimelineType.attachment then
|
||||
if testBit(timelineMode[i], NOT_LAST) then
|
||||
skipSubsequent = true
|
||||
else
|
||||
timelineBlend = MixBlend.setup
|
||||
end
|
||||
end
|
||||
if timelineMode[i] == SUBSEQUENT then
|
||||
if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
|
||||
timelineBlend = blend
|
||||
alpha = alphaMix
|
||||
elseif clearBit(timelineMode[i], NOT_LAST) == FIRST then
|
||||
elseif timelineMode[i] == FIRST then
|
||||
timelineBlend = MixBlend.setup
|
||||
alpha = alphaMix
|
||||
elseif clearBit(timelineMode[i], NOT_LAST) == HOLD then
|
||||
elseif timelineMode[i] == HOLD then
|
||||
timelineBlend = MixBlend.setup
|
||||
alpha = alphaHold
|
||||
else
|
||||
@ -459,13 +479,11 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
from.totalAlpha = from.totalAlpha + alpha
|
||||
if timeline.type == Animation.TimelineType.rotate then
|
||||
self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
|
||||
elseif timeline.type == Animation.TimelineType.attachment then
|
||||
self:applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments)
|
||||
else
|
||||
if timelineBlend == MixBlend.setup then
|
||||
if timeline.type == Animation.TimelineType.attachment then
|
||||
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
|
||||
if (drawOrder and timeline.type == Animation.TimelineType.drawOrder and timelineBlend == MixBlend.setup) then
|
||||
direction = MixDirection._in
|
||||
end
|
||||
timeline:apply(skeleton, animationLast, animationTime, self.events, alpha, timelineBlend, direction)
|
||||
end
|
||||
@ -483,6 +501,38 @@ function AnimationState:applyMixingFrom (to, skeleton, blend)
|
||||
return mix
|
||||
end
|
||||
|
||||
function AnimationState:applyAttachmentTimeline(timeline, skeleton, time, blend, attachments)
|
||||
local slot = skeleton.slots[timeline.slotIndex];
|
||||
if slot.bone.active == false then return end
|
||||
|
||||
local frames = timeline.frames
|
||||
if time < frames[0] then -- Time is before first frame.
|
||||
if blend == MixBlend.setup or blend == MixBlend.first then
|
||||
self:setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
|
||||
end
|
||||
else
|
||||
local frameIndex = 0
|
||||
if (time >= frames[zlen(frames) - 1]) then -- Time is after last frame.
|
||||
frameIndex = zlen(frames) - 1;
|
||||
else
|
||||
frameIndex = Animation.binarySearch(frames, time, 1) - 1;
|
||||
self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
|
||||
end
|
||||
end
|
||||
|
||||
-- If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.
|
||||
if slot.attachmentState <= self.unkeyedState then slot.attachmentState = self.unkeyedState + SETUP end
|
||||
end
|
||||
|
||||
function AnimationState:setAttachment(skeleton, slot, attachmentName, attachments)
|
||||
if (attachmentName == nil) then
|
||||
slot.attachment = nil
|
||||
else
|
||||
slot.attachment = skeleton:getAttachmentByIndex(slot.data.index, attachmentName)
|
||||
end
|
||||
if attachments then slot.attachmentState = self.unkeyedState + CURRENT end
|
||||
end
|
||||
|
||||
function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame)
|
||||
if firstFrame then
|
||||
timelinesRotation[i] = 0
|
||||
@ -866,36 +916,6 @@ function AnimationState:_animationsChanged ()
|
||||
end
|
||||
i = i + 1
|
||||
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:computeHold(entry)
|
||||
|
||||
@ -45,6 +45,7 @@ function Slot.new (data, bone)
|
||||
darkColor = nil,
|
||||
attachment = nil,
|
||||
attachmentTime = 0,
|
||||
attachmentState = 0,
|
||||
deform = {}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user