1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609 |
- -------------------------------------------------------------------------------
- -- Spine Runtimes License Agreement
- -- Last updated January 1, 2020. Replaces all prior versions.
- --
- -- Copyright (c) 2013-2020, Esoteric Software LLC
- --
- -- Integration of the Spine Runtimes into software or otherwise creating
- -- derivative works of the Spine Runtimes is permitted under the terms and
- -- conditions of Section 2 of the Spine Editor License Agreement:
- -- http://esotericsoftware.com/spine-editor-license
- --
- -- Otherwise, it is permitted to integrate the Spine Runtimes into software
- -- or otherwise create derivative works of the Spine Runtimes (collectively,
- -- "Products"), provided that each user of the Products must obtain their own
- -- Spine Editor license and redistribution of the Products in any form must
- -- include this license and copyright notice.
- --
- -- THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
- -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- -- DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
- -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
- -- BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
- -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- -- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- -------------------------------------------------------------------------------
- -- FIXME
- -- All the indexing in this file is zero based. We use zlen()
- -- instead of the # operator. Initialization of number arrays
- -- is performed via utils.newNumberArrayZero. This needs
- -- to be rewritten using one-based indexing for better performance
- local utils = require "spine-lua.utils"
- 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)
- return #array + 1
- end
- local Animation = {}
- function Animation.new (name, timelines, duration)
- if not timelines then error("timelines cannot be nil", 2) end
- local self = {
- name = name,
- timelines = timelines,
- timelineIds = {},
- duration = duration
- }
-
- for i,timeline in ipairs(self.timelines) do
- self.timelineIds[timeline:getPropertyId()] = true
- end
- function self:hasTimeline(id)
- return self.timelineIds[id] == true
- end
- function self:apply (skeleton, lastTime, time, loop, events, alpha, blend, direction)
- 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, blend, direction)
- end
- end
- return self
- end
- local function binarySearch (values, target, step)
- local low = 0
- local high = math.floor(zlen(values) / step - 2)
- if high == 0 then return step end
- local current = math.floor(high / 2)
- while true do
- if values[(current + 1) * step] <= target then
- low = current + 1
- else
- high = current
- end
- if low == high then return (low + 1) * step end
- current = math.floor((low + high) / 2)
- end
- end
- Animation.binarySearch = binarySearch
- local function binarySearch1 (values, target)
- local low = 0
- local high = math.floor(zlen(values) - 2)
- if high == 0 then return 1 end
- local current = math.floor(high / 2)
- while true do
- if values[current + 1] <= target then
- low = current + 1
- else
- high = current
- end
- if low == high then return low + 1 end
- current = math.floor((low + high) / 2)
- end
- end
- local function linearSearch (values, target, step)
- local i = 0
- local last = zlen(values) - step
- while i <= last do
- if (values[i] > target) then return i end
- i = i + step
- end
- return -1
- end
- Animation.MixBlend = {
- setup = 0,
- first = 1,
- replace = 2,
- add = 3
- }
- local MixBlend = Animation.MixBlend
- Animation.MixDirection = {
- _in = 0, out = 1
- }
- local MixDirection = Animation.MixDirection
- 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,
- twoColor = 14
- }
- local TimelineType = Animation.TimelineType
- local SHL_24 = 16777216
- local SHL_27 = 134217728
- Animation.CurveTimeline = {}
- function Animation.CurveTimeline.new (frameCount)
- local LINEAR = 0
- local STEPPED = 1
- local BEZIER = 2
- local BEZIER_SIZE = 10 * 2 - 1
- local self = {
- curves = utils.newNumberArrayZero((frameCount - 1) * BEZIER_SIZE) -- type, x, y, ...
- }
- function self:getFrameCount ()
- return math.floor(zlen(self.curves) / BEZIER_SIZE) + 1
- end
- function self:setStepped (frameIndex)
- self.curves[frameIndex * BEZIER_SIZE] = STEPPED
- end
- function self:getCurveType (frameIndex)
- local index = frameIndex * BEZIER_SIZE
- if index == zlen(self.curves) then return LINEAR end
- local type = self.curves[index]
- if type == LINEAR then return LINEAR end
- if type == STEPPED then return STEPPED end
- return BEZIER
- end
- function self:setCurve (frameIndex, cx1, cy1, cx2, cy2)
- local tmpx = (-cx1 * 2 + cx2) * 0.03
- local tmpy = (-cy1 * 2 + cy2) * 0.03
- local dddfx = ((cx1 - cx2) * 3 + 1) * 0.006
- local dddfy = ((cy1 - cy2) * 3 + 1) * 0.006
- local ddfx = tmpx * 2 + dddfx
- local ddfy = tmpy * 2 + dddfy
- local dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667
- local dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667
- local i = frameIndex * BEZIER_SIZE
- local curves = self.curves
- curves[i] = BEZIER
- i = i + 1
- local x = dfx
- local y = dfy
- local n = i + BEZIER_SIZE - 1
- while i < n do
- curves[i] = x
- curves[i + 1] = y
- dfx = dfx + ddfx
- dfy = dfy + ddfy
- ddfx = ddfx + dddfx
- ddfy = ddfy + dddfy
- x = x + dfx
- y = y + dfy
- i = i + 2
- end
- end
- function self:getCurvePercent (frameIndex, percent)
- percent = utils.clamp(percent, 0, 1)
- local curves = self.curves
- local i = frameIndex * BEZIER_SIZE
- local type = curves[i]
- if type == LINEAR then return percent end
- if type == STEPPED then return 0 end
- i = i + 1
- local x
- local n = i + BEZIER_SIZE - 1
- local start = i
- while i < n do
- x = curves[i]
- if x >= percent then
- local prevX, prevY
- if i == start then
- prevX = 0
- prevY = 0
- else
- prevX = curves[i - 2]
- prevY = curves[i - 1]
- end
- return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX)
- end
- i = i + 2
- end
- local y = curves[i - 1]
- return y + (1 - y) * (percent - x) / (1 - x) -- Last point is 1,1.
- end
- return self
- end
- Animation.RotateTimeline = {}
- Animation.RotateTimeline.ENTRIES = 2
- Animation.RotateTimeline.PREV_TIME = -2
- Animation.RotateTimeline.PREV_ROTATION = -1
- Animation.RotateTimeline.ROTATION = 1
- function Animation.RotateTimeline.new (frameCount)
- local ENTRIES = Animation.RotateTimeline.ENTRIES
- 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)
- self.boneIndex = -1
- self.frames = utils.newNumberArrayZero(frameCount * 2)
- self.type = TimelineType.rotate
- function self:getPropertyId ()
- return TimelineType.rotate * SHL_24 + self.boneIndex
- end
- function self:setFrame (frameIndex, time, degrees)
- frameIndex = frameIndex * 2
- self.frames[frameIndex] = time
- self.frames[frameIndex + ROTATION] = degrees
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local bone = skeleton.bones[self.boneIndex]
- if not bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- bone.rotation = bone.data.rotation
- elseif blend == MixBlend.first then
- local r = bone.data.rotation - bone.rotation
- bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
- end
- return
- end
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- 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.
- bone.rotation = bone.rotation + r * alpha;
- elseif blend == MixBlend.add then
- bone.rotation = bone.rotation + r * alpha;
- end
- return;
- end
- -- Interpolate between the last frame and the current frame.
- local frame = binarySearch(frames, time, ENTRIES)
- local prevRotation = frames[frame + PREV_ROTATION]
- local frameTime = frames[frame]
- local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
- local r = frames[frame + ROTATION] - prevRotation
- 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
- return self
- end
- Animation.TranslateTimeline = {}
- Animation.TranslateTimeline.ENTRIES = 3
- function Animation.TranslateTimeline.new (frameCount)
- local ENTRIES = Animation.TranslateTimeline.ENTRIES
- local PREV_TIME = -3
- local PREV_X = -2
- local PREV_Y = -1
- local X = 1
- local Y = 2
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.boneIndex = -1
- self.type = TimelineType.translate
- function self:getPropertyId ()
- return TimelineType.translate * SHL_24 + self.boneIndex
- end
- function self:setFrame (frameIndex, time, x, y)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + X] = x
- self.frames[frameIndex + Y] = y
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local bone = skeleton.bones[self.boneIndex]
- if not bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- bone.x = bone.data.x
- bone.y = bone.data.y
- elseif blend == MixBlend.first then
- bone.x = bone.x + (bone.data.x - bone.x) * alpha
- bone.y = bone.y + (bone.data.y - bone.y) * alpha
- end
- return
- end
- 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));
- x = x + (frames[frame + X] - x) * percent
- y = y + (frames[frame + Y] - y) * percent
- end
- if blend == MixBlend.setup then
- bone.x = bone.data.x + x * alpha
- bone.y = bone.data.y + y * alpha
- elseif blend == MixBlend.first or blend == MixBlend.replace then
- bone.x = bone.x + (bone.data.x + x - bone.x) * 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
- return self
- end
- Animation.ScaleTimeline = {}
- Animation.ScaleTimeline.ENTRIES = Animation.TranslateTimeline.ENTRIES
- function Animation.ScaleTimeline.new (frameCount)
- local ENTRIES = Animation.ScaleTimeline.ENTRIES
- local PREV_TIME = -3
- local PREV_X = -2
- local PREV_Y = -1
- local X = 1
- local Y = 2
- local self = Animation.TranslateTimeline.new(frameCount)
- self.type = TimelineType.scale
- function self:getPropertyId ()
- return TimelineType.scale * SHL_24 + self.boneIndex
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local bone = skeleton.bones[self.boneIndex]
- if not bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- bone.scaleX = bone.data.scaleX
- bone.scaleY = bone.data.scaleY
- elseif blend == MixBlend.first then
- bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha
- bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha
- end
- return
- end
- local x = 0
- local y = 0
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- 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))
- 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
- 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
- local bx = 0
- local by = 0
- 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
- 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
- end
- return self
- end
- Animation.ShearTimeline = {}
- Animation.ShearTimeline.ENTRIES = Animation.TranslateTimeline.ENTRIES
- function Animation.ShearTimeline.new (frameCount)
- local ENTRIES = Animation.ShearTimeline.ENTRIES
- local PREV_TIME = -3
- local PREV_X = -2
- local PREV_Y = -1
- local X = 1
- local Y = 2
- local self = Animation.TranslateTimeline.new(frameCount)
- self.type = TimelineType.shear
- function self:getPropertyId ()
- return TimelineType.shear * SHL_24 + self.boneIndex
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local bone = skeleton.bones[self.boneIndex]
- if not bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- bone.shearX = bone.data.shearX
- bone.shearY = bone.data.shearY
- elseif blend == MixBlend.first then
- bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha
- bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha
- end
- return
- end
- 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))
- x = x + (frames[frame + X] - x) * percent
- y = y + (frames[frame + Y] - y) * percent
- end
- if blend == MixBlend.setup then
- bone.shearX = bone.data.shearX + x * alpha
- bone.shearY = bone.data.shearY + y * alpha
- elseif blend == MixBlend.first or blend == MixBlend.replace then
- bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * 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
- return self
- end
- Animation.ColorTimeline = {}
- Animation.ColorTimeline.ENTRIES = 5
- function Animation.ColorTimeline.new (frameCount)
- local ENTRIES = Animation.ColorTimeline.ENTRIES
- local PREV_TIME = -5
- local PREV_R = -4
- local PREV_G = -3
- local PREV_B = -2
- local PREV_A = -1
- local R = 1
- local G = 2
- local B = 3
- local A = 4
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.slotIndex = -1
- self.type = TimelineType.color
- function self:getPropertyId ()
- return TimelineType.color * SHL_24 + self.slotIndex
- end
- function self:setFrame (frameIndex, time, r, g, b, a)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + R] = r
- self.frames[frameIndex + G] = g
- self.frames[frameIndex + B] = b
- self.frames[frameIndex + A] = a
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local slot = skeleton.slots[self.slotIndex]
- if not slot.bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- slot.color:setFrom(slot.data.color)
- elseif blend == MixBlend.first then
- local color = slot.color
- local setup = slot.data.color
- color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
- (setup.a - color.a) * alpha)
- end
- return
- end
- local r, g, b, a
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- local i = zlen(frames)
- r = frames[i + PREV_R]
- g = frames[i + PREV_G]
- b = frames[i + PREV_B]
- a = frames[i + PREV_A]
- else
- -- Interpolate between the last frame and the current frame.
- local frame = binarySearch(frames, time, ENTRIES)
- r = frames[frame + PREV_R]
- g = frames[frame + PREV_G]
- b = frames[frame + PREV_B]
- a = frames[frame + PREV_A]
- local frameTime = frames[frame]
- local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
- 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
- r = r + (frames[frame + R] - r) * percent
- g = g + (frames[frame + G] - g) * percent
- b = b + (frames[frame + B] - b) * percent
- a = a + (frames[frame + A] - a) * percent
- end
- if alpha == 1 then
- slot.color:set(r, g, b, a)
- else
- local color = slot.color
- 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)
- end
- end
- return self
- end
- Animation.TwoColorTimeline = {}
- Animation.TwoColorTimeline.ENTRIES = 8
- function Animation.TwoColorTimeline.new (frameCount)
- local ENTRIES = Animation.TwoColorTimeline.ENTRIES
- local PREV_TIME = -8
- local PREV_R = -7
- local PREV_G = -6
- local PREV_B = -5
- local PREV_A = -4
- local PREV_R2 = -3
- local PREV_G2 = -2
- local PREV_B2 = -1
- local R = 1
- local G = 2
- local B = 3
- local A = 4
- local R2 = 5
- local G2 = 6
- local B2 = 7
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.slotIndex = -1
- self.type = TimelineType.twoColor
- function self:getPropertyId ()
- return TimelineType.twoColor * SHL_24 + self.slotIndex
- end
- function self:setFrame (frameIndex, time, r, g, b, a, r2, g2, b2)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + R] = r
- self.frames[frameIndex + G] = g
- self.frames[frameIndex + B] = b
- self.frames[frameIndex + A] = a
- self.frames[frameIndex + R2] = r2
- self.frames[frameIndex + G2] = g2
- self.frames[frameIndex + B2] = b2
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local slot = skeleton.slots[self.slotIndex]
- if not slot.bone.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- slot.color:setFrom(slot.data.color)
- slot.darkColor:setFrom(slot.data.darkColor)
- elseif blend == MixBlend.first then
- local light = slot.color
- local dark = slot.darkColor
- local setupLight = slot.data.color
- local setupDark = slot.data.darkColor
- light:add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,
- (setupLight.a - light.a) * alpha)
- dark:add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0)
- end
- return
- end
- local r, g, b, a, r2, g2, b2
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- local i = zlen(frames)
- r = frames[i + PREV_R]
- g = frames[i + PREV_G]
- b = frames[i + PREV_B]
- a = frames[i + PREV_A]
- r2 = frames[i + PREV_R2]
- g2 = frames[i + PREV_G2]
- b2 = frames[i + PREV_B2]
- else
- -- Interpolate between the last frame and the current frame.
- local frame = binarySearch(frames, time, ENTRIES)
- r = frames[frame + PREV_R]
- g = frames[frame + PREV_G]
- b = frames[frame + PREV_B]
- a = frames[frame + PREV_A]
- r2 = frames[frame + PREV_R2]
- g2 = frames[frame + PREV_G2]
- b2 = frames[frame + PREV_B2]
- local frameTime = frames[frame]
- local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
- 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
- r = r + (frames[frame + R] - r) * percent
- g = g + (frames[frame + G] - g) * percent
- b = b + (frames[frame + B] - b) * percent
- a = a + (frames[frame + A] - a) * percent
- r2 = r2 + (frames[frame + R2] - r2) * percent
- g2 = g2 + (frames[frame + G2] - g2) * percent
- b2 = b2 + (frames[frame + B2] - b2) * percent
- end
- if alpha == 1 then
- slot.color:set(r, g, b, a)
- slot.darkColor:set(r2, g2, b2, 1)
- else
- local light = slot.color
- local dark = slot.darkColor
- if blend == MixBlend.setup then
- light:setFrom(slot.data.color)
- dark:setFrom(slot.data.darkColor)
- end
- light:add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha)
- dark:add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0)
- end
- end
- return self
- end
- Animation.AttachmentTimeline = {}
- function Animation.AttachmentTimeline.new (frameCount)
- local self = {
- frames = utils.newNumberArrayZero(frameCount), -- time, ...
- attachmentNames = {},
- slotIndex = -1,
- type = TimelineType.attachment
- }
- function self:getFrameCount ()
- return zlen(self.frames)
- end
- function self:setFrame (frameIndex, time, attachmentName)
- self.frames[frameIndex] = time
- self.attachmentNames[frameIndex] = attachmentName
- end
- function self:getPropertyId ()
- return TimelineType.attachment * SHL_24 + self.slotIndex
- 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))
- end
- return;
- end
- 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
- end
- return
- end
- local frameIndex = 0
- if time >= frames[zlen(frames) - 1] then
- frameIndex = zlen(frames) - 1
- else
- frameIndex = binarySearch(frames, time, 1) - 1
- end
- attachmentName = self.attachmentNames[frameIndex]
- if not attachmentName then
- slot:setAttachment(nil)
- else
- slot: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
- self.type = TimelineType.deform
- function self:getPropertyId ()
- return TimelineType.deform * SHL_27 + self.attachment.id + 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, blend, direction)
- local slot = skeleton.slots[self.slotIndex]
- if not slot.bone.active then return end
- 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 slotAttachment.deformAttachment ~= self.attachment then return end
- local frames = self.frames
- local deformArray = slot.deform
- if #(deformArray) == 0 then blend = MixBlend.setup end
- local frameVertices = self.frameVertices
- local vertexCount = #(frameVertices[0])
- if time < frames[0] then
- local vertexAttachment = slotAttachment;
- if blend == MixBlend.setup then
- slot.deform = {}
- return;
- elseif blend == MixBlend.first then
- if (alpha == 1) then
- slot.deform = {}
- return;
- end
- local deform = utils.setArraySize(deformArray, vertexCount)
- if (vertexAttachment.bones == nil) then
- local setupVertices = vertexAttachment.vertices
- local i = 1
- while i <= vertexCount do
- deform[i] = deform[i] + (setupVertices[i] - deform[i]) * alpha
- i = i + 1
- end
- else
- alpha = 1 - alpha
- local i = 1
- while i <= vertexCount do
- deform[i] = deform[i] * alpha
- i = i + 1
- end
- end
- end
- return
- end
- local deform = utils.setArraySize(deformArray, vertexCount)
- if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
- local lastVertices = frameVertices[zlen(frames) - 1]
- if alpha == 1 then
- 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
- deform[i] = deform[i] + lastVertices[i] - setupVertices[i]
- i = i + 1
- end
- else
- -- Weighted deform offsets, with alpha.
- local i = 1
- while i <= vertexCount do
- deform[i] = deform[i] + lastVertices[i]
- i = i + 1
- end
- end
- else
- local i = 1
- while i <= vertexCount do
- deform[i] = lastVertices[i]
- i = i + 1
- end
- 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 setup = setupVertices[i]
- deform[i] = setup + (lastVertices[i] - setup) * alpha
- i = i + 1
- end
- else
- -- Weighted deform offsets, with alpha.
- local i = 1
- while i <= vertexCount do
- deform[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
- deform[i] = deform[i] + (lastVertices[i] - deform[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
- deform[i] = deform[i] + (lastVertices[i] - setupVertices[i]) * alpha
- i = i + 1
- end
- else
- -- Weighted deform offsets, with alpha.
- local i = 1
- while i <= vertexCount do
- deform[i] = deform[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
- deform[i] = deform[i] + (lastVertices[i] - setupVertices[i]) * alpha
- i = i + 1
- end
- else
- -- Weighted deform offsets, with alpha.
- local i = 1
- while i <= vertexCount do
- deform[i] = deform[i] + lastVertices[i] * alpha
- i = i + 1
- end
- end
- 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
- 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]
- deform[i] = deform[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]
- deform[i] = deform[i] + prev + (nextVertices[i] - prev) * percent
- i = i + 1
- end
- end
- else
- local i = 1
- while i <= vertexCount do
- local prev = prevVertices[i]
- deform[i] = prev + (nextVertices[i] - prev) * percent
- i = i + 1
- end
- 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]
- deform[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]
- deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha
- i = i + 1
- end
- end
- elseif blend == MixBlend.first or blend == MixBlend.replace then
- local i = 1
- while i <= vertexCount do
- local prev = prevVertices[i]
- deform[i] = deform[i] + (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha
- i = i + 1
- 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
- local prev = prevVertices[i]
- deform[i] = deform[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]
- deform[i] = deform[i] + (prev + (nextVertices[i] - prev) * percent) * alpha
- i = i + 1
- end
- end
- end
- end
- end
- return self
- end
- Animation.EventTimeline = {}
- function Animation.EventTimeline.new (frameCount)
- local self = {
- frames = utils.newNumberArrayZero(frameCount),
- events = {},
- type = TimelineType.event
- }
- function self:getPropertyId ()
- return TimelineType.event * SHL_24
- end
- function self:getFrameCount ()
- return zlen(self.frames)
- end
- function self:setFrame (frameIndex, event)
- self.frames[frameIndex] = event.time
- self.events[frameIndex] = event
- end
- -- Fires events for frames > lastTime and <= time.
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- if not firedEvents then return end
- local frames = self.frames
- local frameCount = zlen(frames)
- if lastTime > time then -- Fire events after last time for looped animations.
- self:apply(skeleton, lastTime, 999999, firedEvents, alpha, blend, direction)
- lastTime = -1
- elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
- return
- end
- if time < frames[0] then return end -- Time is before first frame.
- local frame
- if lastTime < frames[0] then
- frame = 0
- else
- frame = binarySearch1(frames, lastTime)
- local frame = frames[frame]
- while frame > 0 do -- Fire multiple events with the same frame.
- if frames[frame - 1] ~= frame then break end
- frame = frame - 1
- end
- end
- local events = self.events
- while frame < frameCount and time >= frames[frame] do
- table.insert(firedEvents, events[frame])
- frame = frame + 1
- end
- end
- return self
- end
- Animation.DrawOrderTimeline = {}
- function Animation.DrawOrderTimeline.new (frameCount)
- local self = {
- frames = utils.newNumberArrayZero(frameCount),
- drawOrders = {},
- type = TimelineType.drawOrder
- }
- function self:getPropertyId ()
- return TimelineType.drawOrder * SHL_24
- end
- function self:getFrameCount ()
- return zlen(self.frames)
- end
- function self:setFrame (frameIndex, time, drawOrder)
- self.frames[frameIndex] = time
- self.drawOrders[frameIndex] = drawOrder
- end
- 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]
- end
- return;
- end
- local frames = self.frames
- if time < frames[0] then
- if blend == MixBlend.setup or blend == MixBlend.first then
- for i,slot in ipairs(slots) do
- drawOrder[i] = slots[i]
- end
- end
- return
- end
- local frame
- if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
- frame = zlen(frames) - 1
- else
- frame = binarySearch1(frames, time) - 1
- end
- local drawOrderToSetupIndex = self.drawOrders[frame]
- if not drawOrderToSetupIndex then
- for i,slot in ipairs(slots) do
- drawOrder[i] = slots[i]
- end
- else
- for i,setupIndex in ipairs(drawOrderToSetupIndex) do
- drawOrder[i] = skeleton.slots[setupIndex]
- end
- end
- end
- return self
- end
- Animation.IkConstraintTimeline = {}
- Animation.IkConstraintTimeline.ENTRIES = 6
- function Animation.IkConstraintTimeline.new (frameCount)
- local ENTRIES = Animation.IkConstraintTimeline.ENTRIES
- local PREV_TIME = -6
- local PREV_MIX = -5
- local PREV_SOFTNESS = -4
- local PREV_BEND_DIRECTION = -3
- local PREV_COMPRESS = -2
- local PREV_STRETCH = -1
- local MIX = 1
- local SOFTNESS = 2
- local BEND_DIRECTION = 3
- local COMPRESS = 4
- local STRETCH = 5
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, softness, bendDirection, compress, stretch, ...
- self.ikConstraintIndex = -1
- self.type = TimelineType.ikConstraint
- function self:getPropertyId ()
- return TimelineType.ikConstraint * SHL_24 + self.ikConstraintIndex
- end
- function self:setFrame (frameIndex, time, mix, softness, bendDirection, compress, stretch)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + MIX] = mix
- self.frames[frameIndex + SOFTNESS] = softness
- self.frames[frameIndex + BEND_DIRECTION] = bendDirection
- if (compress) then
- self.frames[frameIndex + COMPRESS] = 1
- else
- self.frames[frameIndex + COMPRESS] = 0
- end
- if (stretch) then
- self.frames[frameIndex + STRETCH] = 1
- else
- self.frames[frameIndex + STRETCH] = 0
- end
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
- if not constraint.active then return end
- if time < frames[0] then
- if blend == MixBlend.setup then
- constraint.mix = constraint.data.mix
- constraint.softness = constraint.data.softness
- constraint.bendDirection = constraint.data.bendDirection
- constraint.compress = constraint.data.compress
- constraint.stretch = constraint.data.stretch
- elseif blend == MixBlend.first then
- constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
- constraint.softness = constraint.softness + (constraint.data.softness - constraint.softness) * alpha
- constraint.bendDirection = constraint.data.bendDirection
- constraint.compress = constraint.data.compress
- constraint.stretch = constraint.data.stretch
- end
- return
- end
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- if blend == MixBlend.setup then
- constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
- constraint.softness = constraint.data.softness + (frames[zlen(frames) + PREV_SOFTNESS] - constraint.data.softness) * alpha
- if direction == MixDirection.out then
- constraint.bendDirection = constraint.data.bendDirection
- constraint.compress = constraint.data.compress
- constraint.stretch = constraint.data.stretch
- else
- constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]);
- if (math_floor(frames[zlen(frames) + PREV_COMPRESS]) == 1) then constraint.compress = true else constraint.compress = false end
- if (math_floor(frames[zlen(frames) + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
- end
- else
- constraint.mix = constraint.mix + (frames[zlen(frames) + PREV_MIX] - constraint.mix) * alpha
- constraint.softness = constraint.softness + (frames[zlen(frames) + PREV_SOFTNESS] - constraint.softness) * alpha
- if direction == MixDirection._in then
- constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION])
- if (math_floor(frames[zlen(frames) + PREV_COMPRESS]) == 1) then constraint.compress = true else constraint.compress = false end
- if (math_floor(frames[zlen(frames) + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
- end
- end
- return
- end
- -- Interpolate between the previous frame and the current frame.
- local frame = binarySearch(frames, time, ENTRIES)
- local mix = frames[frame + PREV_MIX]
- local softness = frames[frame + PREV_SOFTNESS]
- local frameTime = frames[frame]
- local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
- 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
- if blend == MixBlend.setup then
- constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
- constraint.softness = constraint.data.softness + (softness + (frames[frame + SOFTNESS] - softness) * percent - constraint.data.softness) * alpha
- if direction == MixDirection.out then
- constraint.bendDirection = constraint.data.bendDirection
- constraint.compress = constraint.data.compress
- constraint.stretch = constraint.data.stretch
- else
- constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
- if (math_floor(frames[frame + PREV_COMPRESS]) == 1) then constraint.compress = true else constraint.compress = false end
- if (math_floor(frames[frame + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
- end
- else
- constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha
- constraint.softness = constraint.softness + (softness + (frames[frame + SOFTNESS] - softness) * percent - constraint.softness) * alpha
- if direction == MixDirection._in then
- constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
- if (math_floor(frames[frame + PREV_COMPRESS]) == 1) then constraint.compress = true else constraint.compress = false end
- if (math_floor(frames[frame + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
- end
- end
- end
- return self
- end
- Animation.TransformConstraintTimeline = {}
- Animation.TransformConstraintTimeline.ENTRIES = 5
- function Animation.TransformConstraintTimeline.new (frameCount)
- local ENTRIES = Animation.TransformConstraintTimeline.ENTRIES
- local PREV_TIME = -5
- local PREV_ROTATE = -4
- local PREV_TRANSLATE = -3
- local PREV_SCALE = -2
- local PREV_SHEAR = -1
- local ROTATE = 1
- local TRANSLATE = 2
- local SCALE = 3
- local SHEAR = 4
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.transformConstraintIndex = -1
- self.type = TimelineType.transformConstraint
- function self:getPropertyId ()
- return TimelineType.transformConstraint * SHL_24 + self.transformConstraintIndex
- end
- function self:setFrame (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + ROTATE] = rotateMix
- self.frames[frameIndex + TRANSLATE] = translateMix
- self.frames[frameIndex + SCALE] = scaleMix
- self.frames[frameIndex + SHEAR] = shearMix
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
- if not constraint.active then return end
- if time < frames[0] then
- local data = constraint.data
- if blend == MixBlend.setup then
- constraint.rotateMix = data.rotateMix
- constraint.translateMix = data.translateMix
- constraint.scaleMix = data.scaleMix
- constraint.shearMix = data.shearMix
- elseif blend == MixBlend.first then
- constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha
- constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha
- constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha
- constraint.shearMix = constraint.shearMix + (data.shearMix - constraint.shearMix) * alpha
- end
- return
- end
- local rotate = 0
- local translate = 0
- local scale = 0
- local shear = 0
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- local i = zlen(frames)
- 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));
- 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 blend == MixBlend.setup 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
- return self
- end
- Animation.PathConstraintPositionTimeline = {}
- Animation.PathConstraintPositionTimeline.ENTRIES = 2
- function Animation.PathConstraintPositionTimeline.new (frameCount)
- local ENTRIES = Animation.PathConstraintPositionTimeline.ENTRIES
- local PREV_TIME = -2
- local PREV_VALUE = -1
- local VALUE = 1
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.pathConstraintIndex = -1
- self.type = TimelineType.pathConstraintPosition
- function self:getPropertyId ()
- return TimelineType.pathConstraintPosition * SHL_24 + self.pathConstraintIndex
- end
- function self:setFrame (frameIndex, time, value)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + VALUE] = value
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
- if not constraint.active then return end
- if (time < frames[0]) then
- if blend == MixBlend.setup then
- constraint.position = constraint.data.position
- elseif blend == MixBlend.first then
- constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha
- end
- return
- end
- local position = 0
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- 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))
- position = position + (frames[frame + VALUE] - position) * percent
- end
- if blend == MixBlend.setup then
- constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
- else
- constraint.position = constraint.position + (position - constraint.position) * alpha
- end
- end
- return self
- end
- Animation.PathConstraintSpacingTimeline = {}
- Animation.PathConstraintSpacingTimeline.ENTRIES = 2
- function Animation.PathConstraintSpacingTimeline.new (frameCount)
- local ENTRIES = Animation.PathConstraintSpacingTimeline.ENTRIES
- local PREV_TIME = -2
- local PREV_VALUE = -1
- local VALUE = 1
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.pathConstraintIndex = -1
- self.type = TimelineType.pathConstraintSpacing
- function self:getPropertyId ()
- return TimelineType.pathConstraintSpacing * SHL_24 + self.pathConstraintIndex
- end
- function self:setFrame (frameIndex, time, value)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + VALUE] = value
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
- if not constraint.active then return end
- if (time < frames[0]) then
- if blend == MixBlend.setup then
- constraint.spacing = constraint.data.spacing
- elseif blend == MixBlend.first then
- constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha
- end
- return
- end
- local spacing = 0
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- 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))
- spacing = spacing + (frames[frame + VALUE] - spacing) * percent
- end
- if blend == MixBlend.setup then
- constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
- else
- constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
- end
- end
- return self
- end
- Animation.PathConstraintMixTimeline = {}
- Animation.PathConstraintMixTimeline.ENTRIES = 3
- function Animation.PathConstraintMixTimeline.new (frameCount)
- local ENTRIES = Animation.PathConstraintMixTimeline.ENTRIES
- local PREV_TIME = -3
- local PREV_ROTATE = -2
- local PREV_TRANSLATE = -1
- local ROTATE = 1
- local TRANSLATE = 2
- local self = Animation.CurveTimeline.new(frameCount)
- self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
- self.pathConstraintIndex = -1
- self.type = TimelineType.pathConstraintMix
- function self:getPropertyId ()
- return TimelineType.pathConstraintMix * SHL_24 + self.pathConstraintIndex
- end
- function self:setFrame (frameIndex, time, rotateMix, translateMix)
- frameIndex = frameIndex * ENTRIES
- self.frames[frameIndex] = time
- self.frames[frameIndex + ROTATE] = rotateMix
- self.frames[frameIndex + TRANSLATE] = translateMix
- end
- function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
- local frames = self.frames
- local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
- if not constraint.active then return end
- if (time < frames[0]) then
- if blend == MixBlend.setup then
- constraint.rotateMix = constraint.data.rotateMix
- constraint.translateMix = constraint.data.translateMix
- elseif blend == MixBlend.first then
- constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha
- constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha
- end
- return
- end
- local rotate = 0
- local translate = 0
- if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
- 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))
- rotate = rotate + (frames[frame + ROTATE] - rotate) * percent
- translate = translate + (frames[frame + TRANSLATE] - translate) * percent
- end
- if blend == MixBlend.setup 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
- return self
- end
- return Animation
|