Skip to content

Instantly share code, notes, and snippets.

@Stankye
Last active March 23, 2022 13:31
Show Gist options
  • Save Stankye/ae3f34e723873fc361e70ca50daa044a to your computer and use it in GitHub Desktop.
Save Stankye/ae3f34e723873fc361e70ca50daa044a to your computer and use it in GitHub Desktop.
Aseprite script.
----------------------------------------------------------------------
-- Extract animations from sheets.
-- Select or full sprite
-- Somewhere down the line it was originally: https://github.com/aseprite/Aseprite-Script-Examples/blob/master/Tiles%20to%20Layers.lua
-- MIT License
-- https://gist.github.com/Stankye/ae3f34e723873fc361e70ca50daa044a
----------------------------------------------------------------------
local spr = app.activeSprite
-- Checks for a valid sprite
if not spr then
app.alert("There is no sprite to export")
return
end
-- Dialog prompt
local d = Dialog("Split Tiles to Layers")
d:label{
id = "help",
label = "",
text = "Set the width and height to split by:"
}:number{
id = "tile_w",
label = "Tile Width:",
text = "16",
focus = true
}:number{
id = "tile_h",
label = "Tile Height:",
text = "32"
}:number{
id = "framez",
label = "Amount of frames:",
text = "9"
}:entry{
id = "prefix",
label = "File name prefix:",
text = "cleaned_"
}:check{
id = "use_selection",
label = "Use Selection",
selected = false
}:check{
id = "use_tags",
label = "Use Tags:",
selected = false
}:entry{
id = "tags",
label = "Tags:",
text = "Idle:0:4_Walk:5:8_Jump:9:9"
}:button{
id = "ok",
text = "&OK",
focus = true
}:button{
text = "&Cancel"
}:show()
-- Data validation
local data = d.data
if not data.ok then
return
end
function AnimationExtractor(tile_w, tile_h, spr, prefix, og_file, og_path, frame_width, tags, use_tags)
local self = {}
self.tile_w = tile_w
self.tile_h = tile_h
self.spr = spr
self.prefix = prefix
self.og_file = og_file
self.og_path = og_path
self.frame_width = frame_width
self.tags = tags
self.use_tags = use_tags
local rows = math.floor(self.spr.height / self.tile_h)
local cols = math.floor(self.spr.width / self.tile_w)
--[[
Creates a new aseprite file with tagged animations
@param {Number} row The row of the tile to copy
@param {Number} count The overall tile number to be copies (used for naming)
]] --
self.extractToAseprite = function(row, count)
app.command.ImportSpriteSheet {
type = SpriteSheetType.HORIZONTAL,
ui = false,
frameBounds = Rectangle(0, row * self.tile_h, self.frame_width, self.tile_h),
padding = Size(0, 0),
partialTiles = false,
dataFilename = "tmp"
}
local name = self.prefix .. count
app.command.SaveFileAs {
useUI = 'false',
filename = self.og_path .. app.fs.pathSeparator .. name .. ".aseprite"
}
local lspr = app.activeSprite
-- names must be in "[thename]" if you want them to look in the unity importer.
-- TODO, find a good way to shove this in a loop with dialog...
if self.use_tags then
for _, v in ipairs(self.tags) do
local tag_data = {}
for data in string.gmatch(v, "([^" .. ":" .. "]+)") do
table.insert(tag_data, data)
end
local tag = lspr:newTag(tag_data[2], tag_data[3])
local name = tag.name
tag.name = tag_data[1]
end
else
-- CHANGE ME
local tag1 = lspr:newTag(0, 4)
local name = tag1.name
tag1.name = "Idle"
local tag2 = lspr:newTag(5, 8)
local name = tag2.name
tag2.name = "Walk"
local tag3 = lspr:newTag(9, 9)
local name = tag3.name
tag3.name = "Jump"
end
local name = self.prefix .. count
app.command.SaveFileAs {
useUI = 'false',
filename = self.og_path .. app.fs.pathSeparator .. name .. ".aseprite"
}
app.command.CloseFile {
useUI = false
}
end
-- Loop over rows selected
self.gibAnimations = function()
local baseLayer = app.activeLayer
local tileCount = 0
for j = 0, rows - 1 do
app.open(self.og_path .. app.fs.pathSeparator .. self.og_file)
tileCount = tileCount + 1
self.extractToAseprite(j, tileCount)
end
baseLayer.isVisible = false
end
return self
end
-- Get Path / File name info before tmp is written
local og_path = app.fs.filePath(app.activeSprite.filename)
local og_file = app.activeSprite.filename
if data.use_selection then
local tmp_path = app.fs.filePath(app.activeSprite.filename)
app.command.NewSpriteFromSelection()
app.command.SaveFileAs {
useUI = 'false',
filename = tmp_path .. app.fs.pathSeparator .. "tmp_SCRIPT001.aseprite"
}
og_file = "tmp_SCRIPT001.aseprite"
end
local total_width = app.activeSprite.width
local frame_width = math.floor(total_width / data.framez)
-- Tags
local tags = {}
for tag in string.gmatch(data.tags, "([^" .. "_" .. "]+)") do
table.insert(tags, tag)
end
-- Initializes the extractor
local extractor = AnimationExtractor(data.tile_w, data.tile_h, app.activeSprite, data.prefix, og_file, og_path, frame_width,
tags, data.use_tags)
-- Extract and clean up. tmp_ file is not deleted for safety reasons.
app.transaction(function()
extractor.gibAnimations()
app.command.SaveFile()
app.command.CloseFile {
useUI = false
}
end)
local spr = app.activeSprite
-- Checks for a valid sprite
if not spr then
app.alert("Please open a sprite first :(")
return
end
function readconfig(file)
local f = io.open(file, "r")
local lines = f:read("*all")
f:close()
return (lines)
end
-- tfw you start running out of seperator patterns
local configf = "./scripts/conf.txt"
local conf = {}
for cfg in string.gmatch(readconfig(configf), "([^" .. "---" .. "]+)") do
table.insert(conf, cfg)
end
-- Dialog prompt
local d = Dialog("Split Tiles to Layers")
d:label{
id = "help",
label = "",
text = "Build them Rectangles:"
}:number{
id = "tile_w",
label = "Tile Width:",
text = conf[1]
}:number{
id = "tile_h",
label = "Tile Height:",
text = conf[2]
}:number{
id = "frames",
label = "Frames:",
text = conf[3]
}:entry{
id = "animations",
label = "Animations:",
text = conf[4]
}:entry{
id = "filename",
label = "Src File:",
text = conf[5]
}:entry{
id = "recfile",
label = "Rec File:",
text = conf[6]
}:entry{
id = "name",
label = "Name:",
text = "",
focus = true
}:button{
id = "ok",
text = "&OK"
}:button{
text = "&Cancel"
}:show()
-- Data validation
data = d.data
if not data.ok then
return
end
local cf = io.open(configf, "w")
io.output(cf)
io.write(data.tile_w .. "---" .. data.tile_h .. "---" .. data.frames .. "---" .. data.animations .. "---" ..
data.filename .. "---" .. data.recfile .. "---" .. "\n")
io.close(cf)
-- Global cause passing vars is 2 much work :upsidedown:
selection = spr.selection
rectangle = selection.bounds
rx = rectangle.x
ry = rectangle.y
rw = rectangle.width
wh = rectangle.height
-- ..selection.origin.x..":"..selection.origin.y..":"
-- Use this later for bulk edits with color replace
-- Carpets 4 dayz
local rf = io.open(data.recfile, "a")
io.output(rf)
io.write(data.name .. "___" .. rectangle.x .. "___" .. rectangle.y .. "___" .. rectangle.width .. "___" ..
rectangle.height .. "___" .. data.tile_w .. "___" .. data.tile_h .. "___" .. data.frames .. "___" ..
data.animations .. "\n")
io.close(rf)
local newpoint = Point {rectangle.x, rectangle.y + rectangle.height}
selection.origin = newpoint
dofile("./scripts/prep.lua")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment