local cargo = require("lib.cargo") local aseLoader = require("lib.ase-loader") local pprint = require("lib.pprint") -- TODO: Maybe add a texture atlas library for packing frame data -- TODO: For production maybe use another type of loader? (https://github.com/elloramir/packer, https://github.com/EngineerSmith/Runtime-TextureAtlas) local function loadAsepriteSprite(filename) local sprite = {} local ase = aseLoader(filename) sprite.width = ase.header.width sprite.height = ase.header.height sprite.variants = {} local LAYER_CHUNK = 0x2004 local CEL_CHUNK = 0x2005 local TAG_CHUNK = 0x2018 local frames = {} local tags = {} local layers = {} local first_tag for i, ase_frame in ipairs(ase.header.frames) do for _, chunk in ipairs(ase_frame.chunks) do if chunk.type == CEL_CHUNK then local cel = chunk.data local buffer = love.data.decompress("data", "zlib", cel.data) local data = love.image.newImageData(cel.width, cel.height, "rgba8", buffer) local image = love.graphics.newImage(data) local frame = frames[i] if not frame then frame = { image = love.graphics.newCanvas(sprite.width, sprite.height), duration = ase_frame.frame_duration / 1000 } frame.image:setFilter("nearest", "nearest") frames[i] = frame end -- you need to draw in a canvas before. -- frame images can be of different sizes -- but never bigger than the header width and height love.graphics.setCanvas(frame.image) love.graphics.draw(image, cel.x, cel.y) love.graphics.setCanvas() elseif chunk.type == TAG_CHUNK then for j, tag in ipairs(chunk.data.tags) do -- first tag as default if j == 1 then first_tag = tag.name end -- aseprite use 0 notation to begin -- but in lua, everthing starts in 1 tag.to = tag.to + 1 tag.from = tag.from + 1 tag.frames = tag.to - tag.from tags[tag.name] = tag end elseif chunk.type == LAYER_CHUNK then table.insert(layers, chunk.data) end end end for _, tag in pairs(tags) do local variant = {} sprite.variants[tag.name] = variant for i=tag.from,tag.to do table.insert(variant, frames[i]) end end if not sprite.variants.default then sprite.variants.default = {frames[0]} end return sprite end return cargo.init{ dir = "data", loaders = { aseprite = loadAsepriteSprite, ase = loadAsepriteSprite, } }