------------------------------------------------------------------------------- -- Spine Runtimes Software License v2.5 -- -- Copyright (c) 2013-2016, Esoteric Software -- All rights reserved. -- -- You are granted a perpetual, non-exclusive, non-sublicensable, and -- non-transferable license to use, install, execute, and perform the Spine -- Runtimes software and derivative works solely for personal or internal -- use. Without the written permission of Esoteric Software (see Section 2 of -- the Spine Software License Agreement), you may not (a) modify, translate, -- adapt, or develop new applications using the Spine Runtimes or otherwise -- create derivative works or improvements of the Spine Runtimes or (b) remove, -- delete, alter, or obscure any trademarks or any copyright, trademark, patent, -- or other intellectual property or proprietary rights notices on or in the -- Software, including any copy thereof. Redistributions in binary or source -- form must include this license and terms. -- -- THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE -- POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- local setmetatable = setmetatable local table_insert = table.insert local utils = require "spine-lua.utils" local Animation = require "spine-lua.Animation" local AnimationStateData = require "spine-lua.AnimationStateData" local EventType = { start = 0, interrupt = 1, _end = 2, dispose = 3, complete = 4, event = 5 } local EventQueue = {} EventQueue.__index = EventQueue function EventQueue.new (animationState) local self = { objects = {}, animationState = animationState, drainDisabled = false } setmetatable(self, EventQueue) return self end function EventQueue:start (entry) local objects = self.objects table_insert(objects, EventType.start) table_insert(objects, entry) animationState.animationsChanged = true end function EventQueue:interrupt (entry) local objects = self.objects table_insert(objects, EventType.interrupt) table_insert(objects, entry) end function EventQueue:_end (entry) local objects = self.objects table_insert(objects, EventType._end) table_insert(objects, entry) animationState.animationsChanged = true end function EventQueue:dispose (entry) local objects = self.objects table_insert(objects, EventType.dispose) table_insert(objects, entry) end function EventQueue:complete (entry) local objects = self.objects table_insert(objects, EventType.complete) table_insert(objects, entry) end function EventQueue:event (entry, event) local objects = self.objects table_insert(objects, EventType.event) table_insert(objects, entry) table_insert(objects, event) end function EventQueue:drain () if self.drainDisabled then return end -- Not reentrant. self.drainDisabled = true local objects = self.objects local as = self.animationState local i = 1 local n = #objects while i <= n do local _type = objects[i] local entry = objects[i + 1] if _type == EventType.start then if entry.onStart then entry.onStart(entry) end if as.onStart then entry.onStart(entry) end elseif _type == EventType.interrupt then if entry.onInterrupt then entry.onInterrupt(entry) end if as.onInterrupt then entry.onInterrupt(entry) end elseif _type == EventType._end then if entry.onEnd then entry.onEnd(entry) end if as.onEnd then entry.onEnd(entry) end -- fall through in ref impl if entry.onDispose then entry.onDispose(entry) end if as.onDispose then entry.onDispose(entry) end elseif _type == EventType._dispose then if entry.onDispose then entry.onDispose(entry) end if as.onDispose then entry.onDispose(entry) end elseif _type == EventType.complete then if entry.onComplete then entry.onComplete(entry) end if as.onComplete then entry.onComplete(entry) end elseif _type == EventType.event then local event = objects[i + 2] if entry.onEvent then entry.onEvent(entry, event) end if as.onEvent then entry.onEvent(entry, event) end i = i + 1 end i = i + 2 end self:clear() self.drainDisabled = false; end function EventQueue:clear () self.objects[1] = nil -- dirty trick so we don't re-alloc, relies on using # in drain end local AnimationState = {} AnimationState.__index = AnimationState function AnimationState.new (data) if not data then error("data cannot be nil", 2) end local self = { data = data, tracks = {}, events = {}, onStart = nil, onInterrupt = nil, onEnd = nil, onDispose = nil, onComplete = nil, onEvent = nil, queue = nil, propertyIDs = {}, animationsChanged = false, timeScale = 1 } queue = EventQueue.new(self) setmetatable(self, AnimationState) return self end return AnimationState