Load lookdev file and merge alembic at the same time

Hi !

The pipeline I am trying to replace with Shotgun at the moment is working like so:

  • Exporting one alembic cache per asset from the animation scene
  • In the lighting scene, one button gather the latest lookdev scene, and merge the alembic file onto it

I managed to keep those steps but I am not sure I did it the best way, and my implementation does not seem very flexible at the moment.
First when I publish the alembics from animation, to keep track of the upstreampublished file I have this:

def _maya_find_additional_session_dependencies(asset_name):
    ref_paths = set()

    ref_nodes = cmds.ls(references=True)
    for ref_node in ref_nodes:
        ref_path = cmds.referenceQuery(ref_node, filename=True)

        ref_path = ref_path.replace("/", os.path.sep)
        if ref_path:
            if asset_name in ref_path

    return list(ref_paths)

So this gives me a link between the published alembi file and the rigging file of the corresponding asset.

After that, in the Loader I added a _gather function on the Alembic Cache file type. This is to import the lookdev file and merge the alembic in one action, but it is mainly based on names:

def _gather(self, path, sg_publish_data):
    if not cmds.pluginInfo("AbcExport", q = True, loaded = True):

    if not os.path.exists(path):
        raise Exception("File not found on disk - '%s'" % path)

    namespace = "%s_ref" % sg_publish_data.get("code").split("_ref")[0]

    publish_file = self.parent.shotgun.find_one("PublishedFile", [["code", "is", sg_publish_data.get("code")]], ["upstream_published_files"])
    publish_path = self.parent.shotgun.find_one("PublishedFile", [["id", "is", publish_file["upstream_published_files"][0]["id"]]], ["path_cache"])

    lookdev_path = publish_path["path_cache"].replace("/Rigging/", "/Lookdev/")

    project_name = lookdev_path.split("/")[0]
    project_path = path.split(project_name)[0].replace("\\", "/")

    lookdev_path = project_path + lookdev_path

    cmds.file(lookdev_path, i=True,  ignoreVersion = True, mergeNamespacesOnClash=False, namespace=namespace, preserveReferences=True, options="v=0;")
    cmds.AbcImport(path, connect = "/")

I just wanted to know if there was a cleaner way to do that ? I feel like it is not really reliable

Thanks !

Cheers :slight_smile:


Hey Lucas!

I wonder if templates might be useful in getting from a context to a file path? But I think I have some follow-up questions before I can really understand the workflow you’re after.

  • At some point, Lookdev has published a lookdev scene for each asset. Published lookdev scene for an asset is associated to the Lookdev task on the asset.
  • Animation publishes, generates alembic files per asset. Alembic files are associated with the Anim task on the shot.
  • Lighter opens their work file for the shot, launches Loader, loads published Lookdev for desired asset.
  • Expected workflow is that the Load action imports Lookdev scene, and also brings in associated alembic from animation.

Is that correct? I guess I’m not sure if lookdev is per-asset or if it’s for the whole shot. Without knowing all that, I can’t give a definitive answer, but some things to keep in mind:

  • If you’re working in a shot (eg, s100, Lighting task), can you assume that the alembic files are coming from s100, Anim task? If so, could you query Shotgun for PublishedFile entities whose entity field matches that Anim task?
  • Again, if the issue is getting from a Task to a path on disk, templates might be useful here, specifically the paths_from_template() method.

Hopefully that info is helpful; looking forward to hearing more :slight_smile:



Thank you for your answer.

Yes this is exactly correct, and there is indeed one lookdev scene per asset.
The only thing that is changing is that the lighter loads the published alembic, and then the Load action imports Lookdev scene, and also brings in associated alembic from animation.

Does that make sense ?

I think the issue I have is to get a link between the shot (or even the published alembic) and the lookdev scene, and without relying on names, but more on IDs maybe ?

Hope all of that helps to understand, let me know if not :slight_smile:

Thank you for your help !

Cheers !



Here’s a thought: each per-asset alembic is a separate PublishedFile entity, right? There’s a field on PublishedFile called Upstream Published File. If you know at publish time which asset the alembic that you’re publishing represents, then you could determine the latest published lookdev for that asset, and populate Upstream Published File with it. Then, at load time, as you bring in each alembic, you can determine the corresponding lookdev to bring it by querying that field. How does that sound?


Thanks a lot, that should work, I’ll have a try :slight_smile:


The thing is that right now, the only way I can find the asset the alembic represents is based on the name of the asset (which is a part of the namespace of the asset). Is there a way to find asset based not only the name but maybe on the id so it is a bit more reliable ?

Cheers !


Hey Lucas – A few thoughts here:

  • Here’s a route you could go:

    • As I suggested above, at publish time, when you do know the name of the asset you’re publishing .abc’s for (right?), find the latest lookdev PublishedFile for that asset, and add it to the Upstream Published File field for the published .abc.
    • Then at load time, you wouldn’t even really need to go back to the asset name – you could just query the anim .abc’s PublishedFile entity for its Upstream Published File value, and load in that lookdev file.
    • Having said that, if you still do need to get at the asset, the value in Upstream Published File is pointing to the actual PublishedFile entity for the lookdev published against the Asset. So, if you get its Link field (system name of that field is entity) value, you’ll get the Asset.
  • Are you publishing your alembic files in per-asset folders (eg, something like sq001/s102/anim/publish/chicken/sq001.s102_chicken.abc)? If so, you can use sgtk.context_from_path() to go from the path to a Context, then you can query the context from the path. context_from_path() is using Filesystem Location entities to map between a given folder on disk and an entity in Shotgun, so it’s more than just string-matching on the name.

  • There’s also an sgtk.util.find_publish() method that will give you the PublishedFile entity that corresponds to a given path, but I’m not sure that’s too helpful here.

Let me know if you still have questions.


Hey Tannaz,

Thanks a lot for your help, I think I found a way to make it work fine, with the Upstream Published File :slight_smile:

Cheers !


Awesome! So glad that worked out!