Well this is gonna need some more tinkering. I've managed to update the script more to my workflow, so now it exports each tag as an individual zip. It's a bit rough but it works ok for now.
The main issue I'm still facing is that cels are not the full image but it's basically the cropped sprite, which for animations causes the origin to go all over the place due to different individual frame sizes. I need to somehow figure out how to get the origin on a consistent spot despite that.
I can easily get the cel.bounds and I also have the sprite width/height.
aseprite.org/api/image
I think that should be everything I need to math it out but my brain is not braining today. Anyway, here's the updated script for now.
-- Get the active sprite
local sprite = app.sprite
if sprite == nil then
print("No active sprite found.")
return
end
local spriteName = string.match(sprite.filename, "[^/\\]+$")
spriteName = spriteName:gsub("%..*$", "")
-- Create a new dialog
local dlg = Dialog("Export animation for C3 - this will briefly hang :)")
dlg:button{ id="confirm", text="Confirm" }
dlg:button{ id="cancel", text="Cancel" }
dlg:show()
local data = dlg.data
if data.confirm then
-- Extract the directory path of the original sprite file
local originalFilePath = sprite.filename
local outputFolder = app.fs.joinPath(string.match(originalFilePath, "^(.-)([^\\/]-%.?([^%.\\/]*))$"), "tmp-export-for-c3")
if outputFolder == nil then
print("Failed to determine output folder.")
return
end
for i, tag in ipairs(sprite.tags) do
-- Use the name that was set in the dialog or the file name if no name was specified in the dialog
local defaultAnimationName = tag.name
-- Construct the JSON data
local jsonData = {
["use-raw-folder-names"] = true,
["animation"] = {
["name"] = tag.name,
["speed"] = 0,
["loop"] = false,
["ping-pong"] = false,
["repeat-count"] = tag.repeats or 1,
["repeat-to"] = 0,
["frame-durations"] = {},
["frame-tags"] = {},
["frame-image-points"] = {}
}
}
if tag.aniDir <= 1 then
jsonData["animation"]["loop"] = true
else
jsonData["animation"]["ping-pong"] = true
end
local fps = math.floor((1000 / (tag.fromFrame.duration * 1000)) + 0.5)
jsonData["animation"]["speed"] = fps
-- Flatten to merge all layers
local dupe = Sprite(sprite)
dupe:flatten()
local origin = {{
originX = 0.5,
originY = 0.5
}}
for i, cel in ipairs(dupe.cels) do
if cel.frameNumber >= tag.fromFrame.frameNumber and cel.frameNumber <= tag.toFrame.frameNumber then
local filename = app.fs.joinPath(outputFolder, i .. ".png")
cel.image:saveAs(filename)
--jsonData["frame-image-points"].inser = {"originX":3, "originY":3}
table.insert(jsonData["animation"]["frame-image-points"], origin)
local lfps = math.floor((1000 / (cel.frame.duration * 1000)) + 0.5)
table.insert(jsonData["animation"]["frame-durations"], math.floor((fps / lfps) + 0.5))
end
end
dupe:close()
--app.command.Undo()
-- Write JSON data to file
local jsonFilename = app.fs.joinPath(outputFolder, "c3-import-settings.json")
local jsonFile = io.open(jsonFilename, "w")
if jsonFile then
jsonFile:write(json.encode(jsonData))
jsonFile:close()
else
print("Failed to generate JSON file.")
return
end
local pathSeparator = package.config:sub(1, 1)
-- Choose the appropriate zip command based on the operating system
local osType = (pathSeparator == "\\") and "Windows" or "Unix-based"
local zipCmd
local zipFilename = app.fs.joinPath(outputFolder, defaultAnimationName .. ".zip")
if osType:find("Windows") then
-- Use PowerShell on Windows
zipCmd = 'powershell Compress-Archive -Path "' .. outputFolder .. pathSeparator .. "*" .. '" -DestinationPath "' .. zipFilename .. '" -Force'
else
-- Use the zip command on Unix-based systems
zipCmd = 'zip -r "' .. zipFilename .. '" "' .. outputFolder .. pathSeparator .. "*" ..'"'
end
-- Execute the zip command
os.execute(zipCmd)
-- Move the zip file to the new destination path
local directoryPath, fileName = zipFilename:match("(.+)[/\\]([^/\\]+)$")
local newZipFilePath = app.fs.joinPath(directoryPath, "..", fileName)
local moveCommand
if osType:find("Windows") then
-- Windows system
moveCommand = "move".. " " .. zipFilename .. " " .. newZipFilePath
else
-- Unix-like system (Linux, macOS, etc.)
moveCommand = "mv".. " " .. zipFilename .. " " .. newZipFilePath
end
os.execute(moveCommand)
-- Remove the temporary folder
local removeCommand
if osType:find("Windows") then
-- Windows system
removeCommand = "rmdir /s /q" .. " " .. outputFolder
else
-- Unix-like system (Linux, macOS, etc.)
removeCommand = "rm -rf" .. " " .. outputFolder
end
os.execute(removeCommand)
end
end