• Editor
  • How to match an existing atlas?

I've rigged and animated a Spine character and passed it onto someone else for integration with Unity. The developer implementing the character painted a second map as a companion to the atlas. This map uses the atlas UVs and drives emissive features on the shader.

Unfortunately subsequent changes to the character mean that future exports will not give an atlas with the same layout. The character has a new skin that replaces some (but not all) of the sprites on the character, and Spine now exports all of those new sprites on the same atlas, stomping the old packing and invalidating the map the developer made.

Changes like this are expected to be frequent on the project so having to rebuild the supplementary maps each time isn't a friendly workflow, so I'm trying to find a way to preserve that work.

My first attempt was to try and force the subfolder with the new assets not to export separately. Unfortunately the shared assets between skins makes that an unappealing option, and I was only able to even get it to work by turning off the export feature that culls unused images. I could delete the unused images in the project, but I'm not sure if that would guarantee a stable atlas layout. It's also tedious bookkeeping


the rig is fairly complex


and I'd prefer to retain the ability to keep currently unused sprites in the images folder, for convenience or reference.

My next thought was that the texture unpacker could be used to extract the emissive sprites into separate images, and then they could be reassembled to match the new atlas layout by referencing the atlas.txt file for coordinates. Unfortunately I didn't see any way to have the texture packer use another atlas as a template, so I don't know how to execute that second step without parsing the JSON and reassembling the image myself, which right now there isn't time to investigate.

Does anyone know a good way to handle a situation like this, where the Spine sprites need to have supplementary texture info like emission, normal maps, PBR, etc? How can we map this information to the character atlas in a way that stays stable if the atlas changes?


So, I'm not sure if this constitutes a full solution, but here's the workaround I used if anyone else needs this:

1) Copy images folder, with new name imagesAlt
2) Set initial values on all those images. I just needed them to be black, so I used a batch process in photoshop to fill them.
3) Use the texture unpacker tool inside spine to pull the sprites from the modified secondary atlas. I needed to copy the .atlas file and change the image file it's pointed at.

(Steps 1-3 ensure that the imagesAlt folder has all of the images from the original AND any new ones that are added. If the old image sizes have changed then this breaks).

4) Rename images folder temporarily and then rename imagesAlt to images. When exporting, change the packing settings so that the file path has a suffix that stops it from overwriting the base atlas. This resulted in a second atlas that matched the first, but had our emissive maps instead.
5) Revert folder names.

Related Discussions
...

Sorry for the late response.

I'd prefer to retain the ability to keep currently unused sprites in the images folder

You can use a pack.json file so the packer ignore some folders.
Texture packing - Spine User Guide: JSON Configuration

You can keep two image folders, one with the images you use in Spine and one with the images used at runtime. As long as you keep the dimensions and alpha channels identical, the texture packer will pack the images identically. You'd run the texture packer once on each folder to generate two atlases. You can throw away the atlas for the runtime images, as you just need to match their names. Eg page1.png from the images atlas matches page1.png from the shader "map" atlas.

If you are using meshes and whitespace stripping, you'll need to be sure packing both projects uses the current projects to find the mesh vertices. From the UI this is done by checking Current project. From the CLI this is done by specifying one or more Spine project files.

Ah, thanks! That'd be a much better workflow than renaming the folders every time I do an export.

You mention that if the alpha and dimensions stay stable that the packing will be the same, which brings some follow up questions to mind:

  • How is alpha taken into account by the packer? Does the alpha changing matter if the "strip whitespace" options are unchecked?
  • From looking at the packer and unpacker outputs I suspect that the polygonal packing uses the meshes I defined for the rig instead of tracing its own... is that a correct assumption, or does polygonal packing depend on stable alphas as well?
  • I suppose I should also ask: is there a official suggested workflow for multiple map types (ie, emissive, normal, etc), or plans to tool that up at all later?

Yep, alpha is used to strip whitespace. Except for images that are only used for meshes, then the meshes (their union if there are multiple) are used to do the whitespace stripping. In that case the alpha doesn't matter.

It uses the meshes, but it does simplify them if they have many vertices. Without this then polygon packing would take too long (waaay too long).

The official workflow is as above, packing an atlas for each set of images using the same packer settings. I'm not sure how it could be made much better without making it more complex for little gain. We don't want to deal with a packed atlas directly because it can get packed again, so individual images is better, then it's just a matter of packing them so the images match.

Oh, you may need to disable rotation of regions in the atlas. This is because the shader probably expects "up" to be the same directions for all regions. You could pass the rotation to the shader and modify your shader to use that, though disabling rotation in the atlas is easier. The rotation (degrees on the texture atlas region object at runtime) are 0 or 90 when packing rectangles or 0, 90, 180, or 270 when packing polygons.

That clarifies things, thank you!

It uses the meshes, but it does simplify them if they have many vertices. Without this then polygon packing would take too long (waaay too long).

Definitely getting into the weeds since I'm not sure how this could ever actually prove to be a problem, but when simplifying complex meshes does it guarantee the same outline and just cull internal vertices, or is it possible that the mesh silhouette could change slightly?

The official workflow is as above, packing an atlas for each set of images using the same packer settings. I'm not sure how it could be made much better without making it more complex for little gain. We don't want to deal with a packed atlas directly because it can get packed again, so individual images is better, then it's just a matter of packing them so the images match.

Hm. What would an ideal workflow for this look like? :think:

I've turned it around in my head a little. I wouldn't want to hazard a guess as to how difficult the implementation would be, or how many users would actually even need it in the first place (especially given that a workflow does exist), but this is my first swing at what an "ideal" system might look like:

  1. Add support for tracking additional parallel image folders as part of the editor's image library. Possible UI is a button on the images sections of the tree view that adds additional image map folders that user then provide properties for (name, image lookup path, export suffix, default fill colour, etc).

    I think a helpful simplification would be to consider the first image folder provided to be the "primary", and any divergence from the it to be considered extraneous, an error, or a deliberate omission.

  2. The user fills secondary image folders themselves with matching sprites and subfolders. How they export different map types for this is really up to them, this is really more of an advanced tool anyway.

  3. In-editor, image library is able to detect when secondary image folders have images of the same path. In the tree view, when inspecting the image folders each image entry indicates the secondary maps that provide corresponding images, flags any errors, and indicates when a secondary folder doesn't have a sprite for it.

  4. Support for realigning mismatched secondary images. Secondary images have properties that allow them to choose where they're placed inside the primary image to correct alignment errors. If the secondary image is larger, then the primary clips it; if it's smaller, it fills the remaining space with default values.

    I expect it'd be a common use case that a provided secondary map might have different dimensions, because it'd be very difficult to, for instance, sync the alphas of a normal map version of the character in photoshop so that it's trimmed consistently. Given that, it'd be helpful to have a tool that can reconcile those problems inside Spine. Simplest thing is just to give a float2 offset in the properties, more complex would be a visual editor like what's available when messing with UVs in meshes.

  5. A secondary image library specifies a default fill for missing images; for instance, a normal map would want empty entries filled blue while an emissive map would want black.

    Just providing a fill colour covers most of the use cases I can think of, but if you wanted to be more flexible you could also let it reference other folders as fallbacks that would be attempted first.

  6. Support for toggling between map types as a visualization tool. Add an additional editor window that gives a list of image folders active in the project. Selecting one (temporarily) switches the rendering for all sprites and meshes in the editor view to use their namesakes in the given folder so that you can preview it and be sure its working as expected.

    A very helpful setting here would be to let a displayed secondary map be masked by the primary of the alpha; normal maps, for instance, might not have an alpha channel of their own, and depending on various export shenanigans by different art tools alpha channels might even be avoided entirely sometimes. If you really want to go crazy, add the ability to let multiple maps be layered with transparency, and mask off specific colour channels per map!

  7. During export, additional atlases are automatically created for each secondary image folder, and use exactly the same packing layout and settings as the primary (including any page splits). If a secondary map sprite is incorrectly sized it is clipped or filled to match; missing images are filled with the default colour; whatever is needed to match the primary atlas.

    The secondary atlases are generated in the same output folder as the main atlas, but with an appropriate suffix on the file name. They are outputted without an associated .atlas file since they can be assumed to match the primary; once it's exported its in the user's hands, extra information they can choose to slot into their shaders in Unity or what have you.

  8. No runtime or animation support. Since this stuff is pretty much by definition extremely custom, I don't think it'd make sense to support it in the runtime in any way. This would be an editor-only thing, and as far as Spine cares more analogous to packing additional information into hidden colour channels than adding additional independent images.

My thinking is that I'd want it to seamlessly synchronize my secondary maps without me needing to manually take all the extra steps required to create consistent packing and do multiple atlas exports manually, and as long as we're in the neighbourhood it'd be nice to have it do bookkeeping, spot errors, and let me preview the maps on my rig so I can reason about them more effectively.

A potential issue I could see with the above design would be that some users might be wrongly tempted to think of it as an alternative to the skin system; at least on the surface it could see how a new user might think "hey, here's this OTHER thing for providing alternate images for everything". You'd want to be careful with how things are named and worded to dissuade that.

...Ah, sorry for the brain dump there! I think I might've, uh... got a little carried away there.

IanM a écrit

when simplifying complex meshes does it guarantee the same outline and just cull internal vertices, or is it possible that the mesh silhouette could change slightly?

It guarantees that none of the pixels inside the original mesh are lost. This is a surprisingly difficult thing to do!

IanM a écrit

...Ah, sorry for the brain dump there! I think I might've, uh... got a little carried away there.

Haha, no worries! It's a rare skill to think things all the way through. Most users just want a thing done. It's working out the details, and how it fits together with everything else that is the difficult part.

The maps need to be created. They can be generated automatically with tools like SpriteIlluminator. In that case the dimensions and alpha will match. If created by hand, the maps need to be revised if the main image is revised, so there is potential for error. I don't think you'd want to realign maps with the main images in Spine (4). Having a way to detect errors would be nice, but I'm not sure it is best done inside Spine, since Spine doesn't actually make use of the maps.

I would probably write a tool as part of an app's build that compared images dimensions and alpha to identify problems. Some apps benefit from a custom tool like the skeleton viewer (which can be used as the base of such a tool) that displays a skeleton and provides some app specific configuration or rendering (like lighting with maps).

13 jours plus tard
Nate a écrit

It guarantees that none of the pixels inside the original mesh are lost. This is a surprisingly difficult thing to do!

I believe it! Need to watch for a lot of... 8) edge cases.

The maps need to be created. They can be generated automatically with tools like SpriteIlluminator. In that case the dimensions and alpha will match. If created by hand, the maps need to be revised if the main image is revised, so there is potential for error. I don't think you'd want to realign maps with the main images in Spine (4). Having a way to detect errors would be nice, but I'm not sure it is best done inside Spine, since Spine doesn't actually make use of the maps.

Right, I was mainly thinking the specifics of how maps are generated is a "the user needs to figure this out for themselves" problem (aside: thanks for the link to SpriteIlluminator, that looks like an astonishingly handy tool), since the specifics are so use case specific, which means you cant guarantee their process or tools... could be anything from hand drawn pixels to some sort of prototype AI content generator!

In the case of the problem I started this thread with it was absolutely a hand-authoring situation, since the emissive map was being used to light up a character's weapon ahead of an attack. While in this specific situation the developer was expediently adding it post-export by painting over the generated atlas, I was trying to think to what it might look like as a dedicated part of our processes where presumably such maps are generated and exported at the same time as the base character sprites. That stage of the process I've found has a lot of opportunity for errors and desyncs, especially over multiple iterations. For instance, if the layer being exported didn't include the full alpha of the weapon sprite because only the tip of a blade or barrel of a gun was supposed to glow (or it was out of sync with the sprite asset because of revisions, then the auto-trim in the photoshop script might end up exporting a different image size.

That said it's definitely "nice to have" at best; it can obviously be fixed by heading back to the image editor or tweaking your artist's export pipeline. I just figured it'd be a common kind of error, and it'd be a nice convenience feature to be able make a quick fix with. Probably not valuable enough to tool up in a big way, but a float2 offset plus rules about auto-fill and clipping might be enough to execute a quick kludge solution.

As far as whether error detection should be in Spine... TBH, the only error I could imagine it detecting is a sprite size mismatch, anything else is usage dependent. It seems like the information would already be there, though, and it's a convenient point in the pipeline to catch those issues, so might be nice to stick a little warning icon in as a courtesy even if Spine wouldn't have much to do with it..

In both cases definitely not mission critical, probably should have de-emphasized them a bit in that list.

I would probably write a tool as part of an app's build that compared images dimensions and alpha to identify problems. Some apps benefit from a custom tool like the skeleton viewer (which can be used as the base of such a tool) that displays a skeleton and provides some app specific configuration or rendering (like lighting with maps).

Ah, that's a neat idea. I imagine the same could be done directly in Unity as well.


So I've needed to resolve another one of these issues and in the process of figuring out my export workflow I stumbled on an interesting possibility.

What I did was duplicate the skeleton, rename it to the name I wanted for the emissive map, and set the directory for its images folder to be the alternate image folder. I assembled that alternate image folder with the texture unpacker and a photoshop script. By doing this it exported both version in the same export step, with the benefit of skeleton based optimizations like ignoring unused attachments.

So, first, the obvious downside of this is that the duplicated skeleton isn't synced, and gets exported along with the main one. I needed to delete extra atlas and skeleton assets in Unity as a cleanup step. However, I think in a strange way it hit a lot of the wishlist in my previous post:

  • The two map sets have a degree of error checking; if my emissive images were missing a sprite or it was wrong sized, it would throw a warning about a sprite dimension change or show a missing texture indicator. Not robust error checking, but still better than finding out afterwards!

  • I can preview the alternate map by toggling which skeleton is visible. None of the fancy visualization stuff, but even the basics of seeing it in place helps verify that everything has hooked up correctly

  • Everything is outputted in a single export. I do need to set up the duplicated skeleton fresh each time the rig changes (or, if I'm being safe about it, deleting after export and doing it fresh each time).

This isn't a fully formed thought (I am currently badly sleep deprived), but maybe the multiple-skeleton functionality could be expanded to create an expedient way of managing some of this? Like, as an example, with the following changes...

  • Let me duplicate a skeleton by reference, so that it syncs changes, but allow me to change the directory the images folder points at.

  • Instead of a binary export toggle, let me turn off the atlas.txt and .JSON parts of the export and only put out the atlas PNG

That would smooth off the rough edges of the workflow I just tried and make it something I could set up in the file and forget about, instead of a fragile hack that I need to keep an eye on and babysit through an export.

Now, whether that's a sensible thing to add to the skeleton system is another question, I have trouble seeing how those features could cover anything but this extremely weird, hacky use case; however that workaround seemed interesting enough that I had to share it; hopefully it's useful to someone else at the very least, and maybe there's something in there that could inform future editor features.

IanM a écrit

duplicate the skeleton, rename it to the name I wanted for the emissive map, and set the directory for its images folder to be the alternate image folder

That's a clever idea!

IanM a écrit

Let me duplicate a skeleton by reference, so that it syncs changes, but allow me to change the directory the images folder points at.

This synchronization would not be easy to implement.

IanM a écrit

Instead of a binary export toggle, let me turn off the atlas.txt and .JSON parts of the export and only put out the atlas PNG

This isn't hard to do. I'm not sure where such a setting is best placed. It's a bit of a strange feature to do a JSON export with packing and then delete the JSON and atlas files. Putting the setting in the UI is likely to confuse people. It could be a setting in the pack settings JSON, but when Attachments packing is used then the pack.json files are not used. If you can change to packing using Image Folders or running the texture packer separately from JSON export, then the having the setting in the pack.json would work well.

I prefer keeping my images folders clean rather than relying on Attachments to only pack the images that are used. We'd like to provide tools for cleaning the images folders, moving unused images elsewhere. It's also usually better to run the texture packer separately, which means packing everything in the image folders. This is because there is often a build process that involves packing images not just from one skeleton but from many, possible including images used for things other than skeletons.

Such a pack.json setting could be specifically about your use case. If the setting is telling the packer that this atlas is to be used as matching images for another atlas, then it could avoid writing the atlas file and also do checking to ensure the bounds for all the regions match up with the regions having the same name in the other atlas.

Nate a écrit
IanM a écrit

Let me duplicate a skeleton by reference, so that it syncs changes, but allow me to change the directory the images folder points at.

This synchronization would not be easy to implement.

I can imagine, and I have a hard time imagining any use for such a sync to a skeleton in the same scene besides supporting this one strange use case. I only mention it because it's an example of a feature that would sand off one of the remaining friction points in this ad hoc setup. That's not to advocate for the feature itself, just clarifying the pain point/use case; perhaps something the resolves the same problem as a sync would do the job, and be more reasonable!

The specific problem is that changes to the main rig don't propagate to the duplicated one, causing a potential source of errors, possibly subtle ones. My current best workflow workaround for preventing those errors is to make sure I delete and rebuild that skeleton before every export, which is extra manual bookkeeping, or to manually keep track of when I change the rig enough that I need to do so and risk forgetting and having a broken export. If there's a risk that human error could break the atlas sync, as well, that means I need to be checking my export to verify that the sprites line up, which is another thing to worry about.

I'm actually a little leery of asking for tooling for such a clearly ad-hoc workaround, since that feels like just applying duct tape to my ramshackle workflow instead of finding an elegant solution. Additionally, a little bit of discipline around the export process is annoying but considering it's an infrequent operation compared to the time I spend rigging and animating, it's definitely tolerable.

Still, spit-balling some alternatives for discussions sake:

  • Being able to automate this as part of my own export step; I've read that there aren't plans for scripting support, but if there were that'd be one place I could do this; on each export, delete the duped skeleton, duplicate again, rename, change image directory.
  • Actually, is it possible to have an ad-hoc scripting solution? Earlier you linked to a spine visualization tool with source code, and I'm wondering if the spine editor format is exposed in API a way that'd allow me to write a script for this... then maybe be able to hook that up to the export chain somehow so it fires every time there's an export? Or just trigger the editor export from the script itself?
  • Option in export settings to generate the skeleton for specified image folders, then clean it up afterwards. Loses the visualization aspect and another weird thing to turn into an export setting, but would be error free; if that was there, my process might be to make my duplicate skeleton non-exporting and just use it to visually check the results.
  • Somehow make the other skeleton "by reference" or something? I'm not sure if that'd actually represent a simpler approach at all, but I could at least imagine it being useful for use cases other than mine when you want to reference external spine files to animate a multi-character interactions or something. Thinking something like the xref stuff in 3DS MAX.
IanM a écrit

Instead of a binary export toggle, let me turn off the atlas.txt and .JSON parts of the export and only put out the atlas PNG

This isn't hard to do. I'm not sure where such a setting is best placed. It's a bit of a strange feature to do a JSON export with packing and then delete the JSON and atlas files. Putting the setting in the UI is likely to confuse people. It could be a setting in the pack settings JSON, but when Attachments packing is used then the pack.json files are not used. If you can change to packing using Image Folders or running the texture packer separately from JSON export, then the having the setting in the pack.json would work well.

That might work. You're right that it's a strange feature; it's hard to imagine it being helpful for anything else, so sticking it in as a bonus feature in the pack.json doesn't sound unreasonable, it'd be clutter in the export UI that basically nobody would use.

This might also just be something to tool up on the import end; if I gave it a consistent naming scheme, pretty sure I could write a Unity-side import processor that culled out the unused files. A little bit shaky, but as long as we're talking about just sanding off rough edges on a workaround solution for a non-standard use case, it's not unreasonable. After all, it's not even like the extra files even cause problems, they're just clutter!

Though, that makes me wonder... how non-standard is this use case? How many studios using Spine have run into a similar workflow issue with multiple texture maps, and just ended up developing processes or tooling in-house? It strikes me as a feature a lot of game studios might want, particularly for more polished productions or games where normal maps would be valuable for a complex lighting environment... or do studios with those requirements usually self-select out of 2D skeletal animation approaches entirely and go straight to 3D? Hm.

This might also be my bias as a tech artist here talking. It's easy to look at an art problem and start excitedly babbling about how I could write a shader for that. "Art problems? I bet I can solve that by throwing MATH at it!"

...Unrelatedly, I keep hearing people mention something about hammers, problems and nails. Didn't catch what they were saying, though, too busy writing shaders. 😛

Such a pack.json setting could be specifically about your use case. If the setting is telling the packer that this atlas is to be used as matching images for another atlas, then it could avoid writing the atlas file and also do checking to ensure the bounds for all the regions match up with the regions having the same name in the other atlas.

Being able to guarantee that alignment would probably be worth giving up the attachment culling (and I think the rig meshes for polygon packing?) of exporting the rig. One benefit of the machine doing it would be not having to worry about checking the images afterwards to see if they've drifted apart, which shaves another manual step off the process while we're at it.

I prefer keeping my images folders clean rather than relying on Attachments to only pack the images that are used. We'd like to provide tools for cleaning the images folders, moving unused images elsewhere. It's also usually better to run the texture packer separately, which means packing everything in the image folders. This is because there is often a build process that involves packing images not just from one skeleton but from many, possible including images used for things other than skeletons.

Maybe it's a bit sloppy, but I have appreciated being able to keep unused images around without them bloating the atlas! It's let me experiment more easily with image variants or optimizing things by reusing sprites, and keeps me working in Spine instead of my image editor or file system. I've also used it to do a few goofy things like stick in target dummies in enemy animations to demo/visualize how an attack would affect the player... though I suppose I could also do that by sticking those Spine-only images into a folder with a pack.json that prevents export?

As much as I like how it strips out unused images it's not really that much to ask to do a little cleanup here or there, or even just tolerate a few extra sprites in the atlas; it can be a little bit of a hassle on particularly complex rigs, but if you're thinking of tooling that up anyway that makes that a moot point.

  • Modifié
IanM a écrit

Being able to automate this as part of my own export step; I've read that there aren't plans for scripting support, but if there were that'd be one place I could do this; on each export, delete the duped skeleton, duplicate again, rename, change image directory.

I'm afraid there is only the CLI. However, you could write a script that exports your skeleton once, like normal, then swaps the images folder for the alternate (map) images folder, then exports again, then deletes the .json and .atlas file. The script could use a temp folder so it does both exports in a single run of Spine, to avoid the little bit of time for Spine to initialize.

That would give you the export, but not the visualziation. For that, you could export the project to JSON, then import the main skeleton JSON into a new project using the CLI. Then the script would modify the JSON, changing the images path to the map images folder, then import that into the same project. Now you have 2 identical skeletons, one with a different images folder. When you run the script again, it would export to JSON, discard the map skeleton, and then repeat the steps. This gives you synchronization, though it still requires you to run the script.

Note round tripping a project to JSON and back should have Nonessential data checked. It may still loose a few things, like bone icons. In 4.1 will look at that and export more nonessential data.

Actually, is it possible to have an ad-hoc scripting solution? Earlier you linked to a spine visualization tool with source code, and I'm wondering if the spine editor format is exposed in API a way that'd allow me to write a script for this... then maybe be able to hook that up to the export chain somehow so it fires every time there's an export? Or just trigger the editor export from the script itself?

There's no scripting (it's a maintenance issue) and the project format isn't easy to parse. You can export to JSON and muck it all up though. When you specify an export with the CLI, the input file is usually a project, but it can also be a JSON file. That is equivalent to importing the JSON file into a project and then exporting that.

Having the editor launch something after an export is done is interesting. Another way to do that is to have an external tool watch a folder and run when the files change.

IanM a écrit

Somehow make the other skeleton "by reference" or something?

It's powerful, but it gets complicated!

IanM a écrit

...Unrelatedly, I keep hearing people mention something about hammers, problems and nails. Didn't catch what they were saying, though, too busy writing shaders. 😛

:haha:

I'd say it's not uncommon to want to pack map images the same as your main images. A lot of people don't use lighting, but a fair number do.

IanM a écrit

Being able to guarantee that alignment would probably be worth giving up the attachment culling (and I think the rig meshes for polygon packing?) of exporting the rig.

You can specify -j or --project on the CLI when packing so it still uses meshes. Actually the CLI is more powerful than the UI here, because you can specify multiple projects for a single atlas. The mesh polygons are unioned for packing purposes.

IanM a écrit

Maybe it's a bit sloppy, but I have appreciated being able to keep unused images around without them bloating the atlas! It's let me experiment more easily with image variants or optimizing things by reusing sprites, and keeps me working in Spine instead of my image editor or file system. I've also used it to do a few goofy things like stick in target dummies in enemy animations to demo/visualize how an attack would affect the player... though I suppose I could also do that by sticking those Spine-only images into a folder with a pack.json that prevents export?

True, I find it's very easy to have images that aren't actually used. Sometimes it's a pain to move them in and out, eg if they aren't used now but will (or may) be later. Since we can give the packer projects, it could actually support packing only the used images, similar to how it matches up the paths for matches. We'll see about this for 4.1!

For templates and background, yep a pack.json containing { ignore: true } will prevent a folder from being packed.

6 jours plus tard

Seems there's lots of room for me to experimentation with my tool chain! Thanks for the detailed response and explanations. The stuff about CLI is super interesting, and maybe I need to have more of an eye on the command line as an option. Had no idea that you could pack multiple projects into one atlas; I bet that's a lifesaver for mobile!