Help with saving files through script

Hi folks,
I’m attempting to make a script that saves each animation tag in a source file as its own .aseprite file. Here’s the part of the script that’s giving me trouble:

for i,tag in ipairs(spr.tags) do
  local fn = path .. '/' .. title .. '-' .. tag.name
  app.command.SaveFileAs{
    ui=false,
    tag=tag.name,
    filename=fn .. '.aseprite'
  }
end

I just edited the example script found here
I figured ‘tag = tag.name’ would work as a parameter for the SaveFileAs command, but it’s just saving the entire file over again. I can’t find the available parameters for SaveFileAs, and I can’t make heads or tails of the source code. Could someone help me out? Thanks.

(P.S., I realize I can do this very easily with the CLI, I just really want to see this working.)

1 Like

Save As doesn’t have a tag parameter. If you use Save As in the GUI, you’ll see it offers no such options either. Tag selection is only available when Exporting (app.command.SaveFileCopyAs). You’ve probably been looking in the wrong place :]

I don’t know what parameters that takes either though, but hopefully that’ll help. In the worst case, you can script selecting the frames yourself, I believe SaveFileCopyAs will save the selected frames if no frame parameters are provided.

as eishiya says, save as command works differently than export sprite sheet.
i was looking into it and you can provide range as from-frame and to-frame parameters.
and you can get that range from tags, like this:

for i = 1,#spr.tags do
  local fn = path .. '/' .. title .. '-' .. spr.tags[i].name
  app.command.SaveFileAs{
    ui=false,
	["from-frame"] = spr.tags[i].fromFrame.frameNumber-1,
	["to-frame"] = spr.tags[i].toFrame.frameNumber-1,
    filename=fn .. '.aseprite'
  }
end

however… there’s a small issue: it doesn’t work correctly.

when done this way and you have for example two tags on frames [2…4] and [6…7], you will get following:

  1. two new files, correctly named, one with three frames in range 2…4 and one with five frames in range 2…4 + 6 … 7. i don’t know why this happens, if it’s a bug or it has something to do with the fact you’re saving the sprite within the loop.
  1. after the script is done, your active sprite - the original one - remains opened, with the new name, which is the last script exported and the timeline is not updated. i guess that’s not what you need either.

but everything seems to be working fine if you use save file copy as instead:

for i = 1,#spr.tags do
  local fn = path .. '/' .. title .. '-' .. spr.tags[i].name
  app.command.SaveFileCopyAs{
	useUI = false, 
	--["filename-format"] = ".aseprite", 
	["frame-tag"] = spr.tags[i].name, 
    filename=fn .. '.aseprite'
  }
end

(i commented out file-format, because it doesn’t seem to be necessary)

PS. you can use it in this way too:

for i,tag in ipairs(spr.tags) do
  local fn = path .. '/' .. title .. '-' .. tag.name
  app.command.SaveFileCopyAs{
	useUI = false, 
	["frame-tag"] = tag.name, 
    filename=fn .. '.aseprite'
  }
end
3 Likes

Ah, I see what I was doing wrong. SaveFileCopyAs worked. Thanks!

I have one more question though. I know that in the CLI, the --sheet option can package export multiple files into one spritesheet, and I was wondering if there was an easy way to do this through scripting. It doesn’t seem like the ExportSpriteSheet command offers this functionality.
…or should I create another topic for this issue, as it’s not directly related? Sorry, this is my first time posting in the community.

Just a random thought… but a different approach would be to make copies of the whole aseprite file and then for each of those go back and delete the unnecessary frames. I’m new to coding with lua in aseprite but that seems doable since the script can access and modify other files.

i don’t see the problem asking here, but you may want to create a new topic to get more attention to this question.
sadly, i don’t know the answer. it seems like you’re right and there’s no such option to do that through script, but i might be wrong.

If Spoobunk would like to continue this topic in another direction, maybe the SaveFileAs bug could be repeated or broken out into its own topic? That way it’s easier to categorize and to find in a search.

The new .aseprite files contain their original tags. With the bug, it’s possible for the tag to extend beyond the total frame length.

tagsBefore

When the Aseprite file for “Tag2” is opened, the timeline looks like this:

extraTags

I think the problem is around here in the source code. I tried moving the m_selFrames.clear(); around. Without any comments in the code, hard to say whether it was left out for a reason, though. :upside_down_face:

m_selFrames.clear();
bool hasFromFrame = params.has_param("from-frame");
bool hasToFrame = params.has_param("to-frame");
if (hasFromFrame || hasToFrame) {
    if (hasFromFrame && hasToFrame) {
        // frame_t is an alias for int.
        doc::frame_t fromFrame = params.get_as<doc::frame_t>("from-frame");
        doc::frame_t toFrame = params.get_as<doc::frame_t>("to-frame");
        m_selFrames.insert(fromFrame, toFrame);
    } else if (hasFromFrame) {
        // Ideally, this would get the range
        // [fromFrame, active sprite frames length - 1].
        doc::frame_t fromFrame = params.get_as<doc::frame_t>("from-frame");
        m_selFrames.insert(0, fromFrame);
    } else if (hasToFrame) {
        doc::frame_t toFrame = params.get_as<doc::frame_t>("to-frame");           
        m_selFrames.insert(0, toFrame);
    }
    m_adjustFramesByTag = true;
} else {
    m_adjustFramesByTag = false;
}

It’d be nice if there was a graceful way to handle malformed user inputs. I.e., When only a from-frame parameter is supplied, the default could be the last frame index of the active sprite (if any is active).

Cheers,
Jeremy

2 Likes

i wasn’t sure if it’s a bug or incorrect use of SaveFileAs, but if it is a bug, then it probably should be reported in separate topic or on github, so david will more likely notice it.

1 Like
2 Likes