Publishing Alembic From Maya

Publishing Alembic from Maya

This tutorial shows how you can configure Multi Publish to export Alembic files when you are publishing groups of geometry from Maya.

Before You Begin

To publish Alembic Cache files from Maya, make sure that the AbcExport plug-in is loaded in the plug-in manager. You`ll also need a Shot scene with some grouped meshes ready to be published.

Step 1 - Prepare the environment

First, install the tk-multi-publish app for the Shot_Step environment:

As well as adding the app to the environment, this will also download it from the app store and ensure you are running the latest version.

Once installed, open the Shot_Step environment file, typically found at <pipeline_configuration_root>/config/env/Shot_Step.yml and locate the entry for the tk-multi-publish app under the tk-maya engine that you want to modify:

engines:
  tk-maya:
    apps:
      tk-multi-publish:
        ...

Tip: If you want to experiment with a new configuration for an app you can duplicate the entry in the environment and call it something different. Many apps also support a separate display name to help differentiate them in the main Menu.

For this example, modify the app name and display name to be tk-multi-publish-alembic-example and Publish Alembic Example respectively. The initial configuration should now look like:

tk-multi-publish-alembic-example:
  allow_taskless_publishes: true
  display_name: Publish Alembic Example
  expand_single_items: false
  hook_copy_file: default
  hook_post_publish: default
  hook_primary_pre_publish: default
  hook_primary_publish: default
  hook_scan_scene: default
  hook_secondary_pre_publish: default
  hook_secondary_publish: default
  hook_thumbnail: default
  location: {name: tk-multi-publish, type: app_store, version: v0.2.7}
  primary_description: Publish and version up the current work file
  primary_display_name: Current Work File
  primary_icon: ''
  primary_publish_template: maya_shot_publish
  primary_scene_item_type: work_file
  primary_tank_type: Maya Scene
  secondary_outputs: []
  template_work: maya_shot_work

You'll be changing some of these settings but for the full reference take a look at the Multi Publish documentation.

Save the config and then reload the engines and apps in Maya. You'll now have a new Publish Alembic Example entry in the main menu!

Step 2 - Scan the Scene

The first thing the app does is scan the scene for things to publish. To do this, it uses the hook specified by the hook_scan_scene setting. The default implementation just looks for the scene itself, so using this as a starting point, you are going to extend it to additionally find grouped geometry from the scene.

To quickly summarize, you need to do the following to take the default hook as a starting point for this implementation:

  • Locate the default implementation - this can be found in <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/scan_scene_tk-maya.py.
  • Copy this hook to the hooks directory in your current pipeline configuration, e.g. <pc_root>/config/hooks
  • Rename it to something unique, e.g. alembic_example_scan_scene.py
  • Update the hook_scan_scene setting to use this hook: hook_scan_scene: alembic_example_scan_scene

The app will now use your version of the scan scene hook so go ahead and open it up.

The hook returns a list of items that it finds from the scene - the default implementation just finds the scene itself so let's extend it so that it also finds all top level groups that contain one or more meshes. To do this, add the following code at the end of the execute method:

...

# look for root level groups that have meshes as children:
for grp in cmds.ls(assemblies=True, long=True):
    if cmds.ls(grp, dag=True, type="mesh"):
        # include this group as a 'mesh_group' type
        items.append({"type":"mesh_group", "name":grp})

...

You'll notice that when it adds an item to the list, it specifies the type: mesh_group:

items.append({"type":"mesh_group", "name":grp})

You'll see in a minute how this type is used by the app to associate outputs with each item - remember this as it's quite important!

This is the complete version of alembic_example_scan_scene.py

import os
import maya.cmds as cmds

import tank
from tank import Hook
from tank import TankError

class ScanSceneHook(Hook):
    """
    Hook to scan scene for items to publish
    """

    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item

                            name:   String
                                    Name to use for the item in the UI

                            description:    String
                                            Description of the item to use in the UI

                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.

                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.

                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """   

        items = []

        # get the main scene:
        scene_name = cmds.file(query=True, sn=True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")

        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':            
        items.append({"type": "work_file", "name": name})

        # look for root level groups that have meshes as children:
        for grp in cmds.ls(assemblies=True, long=True):
            if cmds.ls(grp, dag=True, type="mesh"):
                # include this group as a 'mesh_group' type
                items.append({"type":"mesh_group", "name":grp})

        return items

Now you've told the app how to find mesh groups in the scene, the next step is to tell it what outputs are available for these groups...

Step 3 - Define the Outputs

The Multi Publish app has two types of output:

  • Primary - Typically the Primary output is used to represent your scene file - there can only be a single Primary output.
  • Secondary - Any additional things to be published are represented as Secondary outputs. You can define as many of these as you need.

These are represented in different areas of the main interface:

This example defines a new Alembic Cache secondary output for all top-level mesh groups within the scene. To do this, edit the secondary_outputs setting in your tk-multi-publish-alembic configuration.

Lets fill in some details and then we'll walk through the important bits:

...
secondary_outputs:
- description: 'Publish Alembic Cache data for the model'
  display_group: Caches
  display_name: Alembic Cache
  icon: 'icons/alembic_output.png'
  name: alembic_cache
  publish_template: maya_shot_mesh_alembic_cache
  required: false
  scene_item_type: mesh_group
  selected: false
  tank_type: 'Alembic Cache'
...

Most of these are self explanatory but for full details please see the Multi Publish reference documentation.

The settings you need to care about for this example are:

name: alembic_cache

The name should be unique across all outputs and can't be primary as this is reserved for the primary output. You'll use this name used later when you are doing the actual publishing...

scene_item_type: mesh_group

Remember the type returned for each item in the scan scene hook back in Step 2? Setting the scene_item_type in the output to the same type tells the app that for all items of type mesh_group you want to publish an Alembic Cache output for it.

Tip: This mechanism allows the association of multiple different outputs with a single item type so if you want to add another output later, for example OBJ export, you can do this without having to modify the scan hook again.

publish_template: maya_shot_mesh_alembic_cache

This setting allows you to specify a template to be used for the published Alembic Cache files. You'll have access to this when you do the publish.

For this example, the following template has been used:

# excerpt from templates.yml
keys:
    ...
    grp_name:
        type: str

paths:        
    ...
    maya_shot_mesh_alembic_cache: '@shot_root/publish/maya/{name}[_{grp_name}].v{version}.abc'

If you are using the default config you can add this to your templates.yml file. Otherwise you may have to tweak the template and/or hooks to work correctly.

tank_type: Alembic Cache

This is the unique publish type that will be used when registering your Alembic Cache files in Shotgun. Again, you'll have access to this when you do the publish.

icon: 'icons/alembic_output.png'

This is the icon the app will use to represent outputs of this new type. Save this icon:

to your configuration's 'icons' directory, e.g. <pc_root>/config/icons/alembic_output.png

Lets see what this looks like. Save the config, reload the app in Maya, open up your test Shot scene and run the Publish Alembic Example command from the menu. If everything has gone to plan, you will now find some Secondary Publishes listed in the UI!

Don't click Publish just yet as you still need to add the code that exports the Alembic Cache files and registers them with Shotgun.

Step 4 - Pre-Publish Validation

Publishing is split into three stages:

  • Pre-Publish
  • Publish
  • Post-Publish.

The first of these, Pre-Publish, allows you to do any validation of the items to be published and report any issues back to the user.

As with scanning the scene, Pre-Publish is implemented via a hook which is defined in the app configuration by the hook_secondary_pre_publish setting.

Follow the instructions in Step 2 to copy the default hook <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/secondary_pre_publish_tk-maya.py to your configuration hooks directory and rename it to alembic_example_secondary_pre_publish.py.

Then edit the setting in the configuration to:

hook_secondary_pre_publish: alembic_example_secondary_pre_publish

The app will now use your version of the Pre-Publish hook so go ahead and open it up.

The hook takes a list of tasks as it's main input:

def execute(self, tasks, work_template, progress_cb, **kwargs):
    ...

This list is based on the users selection from the UI so it only contains things they have selected to be published:

Each task is a dictionary containing an item and an output.

  • The item is the one returned from the scan scene hook back in Step 2.
  • The output contains the name, publish_template and tank_type you configured for the Secondary output in Step 3.

The default implementation for this hook just provides a scaffold to iterate over all the tasks selected by the user and reports an error if it doesn't know how to handle an output.

The user might have deleted or modified the group returned by the scan scene hook so this implementation needs to be extended to make sure they haven't and that everything is ready to be published.

To do this, first replace:

# pre-publish item here, e.g.
#if output["name"] == "foo":
#    ...
#else:
# don't know how to publish this output types!
errors.append("Don't know how to publish this item!")

with

# pre-publish alembic_cache output
if output["name"] == "alembic_cache":
    errors.extend(self._validate_item_for_alembic_cache_publish(item))
else:
    # don't know how to publish this output types!
    errors.append("Don't know how to publish this item!")

Then add a new validation method to the PrePublishHook class:

def _validate_item_for_alembic_cache_publish(self, item):
    """
    Validate that the item is valid to be exported 
    to an alembic cache
    """
    errors = []
    # check that the group still exists:
    if not cmds.objExists(item["name"]):
        errors.append("This group couldn't be found in the scene!")

    # and that it still contains meshes:
    elif not cmds.ls(item["name"], dag=True, type="mesh"):
        errors.append("This group doesn't appear to contain any meshes!")

    # finally return any errors
    return errors

Any problems it finds are returned so that the user is given an opportunity to fix them before publishing. You can of course extend this to do much more comprehensive validation of the items.

This is the complete version of alembic_example_secondary_pre_publish.py

import os
import maya.cmds as cmds

import tank
from tank import Hook
from tank import TankError

class PrePublishHook(Hook):
    """
    Single hook that implements pre-publish functionality
    """
    def execute(self, tasks, work_template, progress_cb, **kwargs):
        """
        Main hook entry point
        :tasks:         List of tasks to be pre-published.  Each task is be a 
                        dictionary containing the following keys:
                        {   
                            item:   Dictionary
                                    This is the item returned by the scan hook 
                                    {   
                                        name:           String
                                        description:    String
                                        type:           String
                                        other_params:   Dictionary
                                    }

                            output: Dictionary
                                    This is the output as defined in the configuration - the 
                                    primary output will always be named 'primary' 
                                    {
                                        name:             String
                                        publish_template: template
                                        tank_type:        String
                                    }
                        }

        :work_template: template
                        This is the template defined in the config that
                        represents the current work file

        :progress_cb:   Function
                        A progress callback to log progress during pre-publish.  Call:

                            progress_cb(percentage, msg)

                        to report progress to the UI

        :returns:       A list of any tasks that were found which have problems that
                        need to be reported in the UI.  Each item in the list should
                        be a dictionary containing the following keys:
                        {
                            task:   Dictionary
                                    This is the task that was passed into the hook and
                                    should not be modified
                                    {
                                        item:...
                                        output:...
                                    }

                            errors: List
                                    A list of error messages (strings) to report    
                        }
        """       
        results = []

        # validate tasks:
        for task in tasks:
            item = task["item"]
            output = task["output"]
            errors = []

            # report progress:
            progress_cb(0, "Validating", task)

             # pre-publish alembic_cache output
            if output["name"] == "alembic_cache":
                errors.extend(self._validate_item_for_alembic_cache_publish(item))
            else:
                # don't know how to publish this output types!
                errors.append("Don't know how to publish this item!")       

            # if there is anything to report then add to result
            if len(errors) > 0:
                # add result:
                results.append({"task":task, "errors":errors})

            progress_cb(100)

        return results

    def _validate_item_for_alembic_cache_publish(self, item):
        """
        Validate that the item is valid to be exported 
        to an alembic cache
        """
        errors = []
        # check that the group still exists:
        if not cmds.objExists(item["name"]):
            errors.append("This group couldn't be found in the scene!")

        # and that it still contains meshes:
        elif not cmds.ls(item["name"], dag=True, type="mesh"):
            errors.append("This group doesn't appear to contain any meshes!")

        # finally return any errors
        return errors

Step 5 - Publish

The Publish stage is where you are going to export an Alembic Cache file to the publish path for each item and then register them with Shotgun. For this example, this is also the final thing you need to do.

This stage is also implemented via a hook which is defined in the app configuration by the hook_secondary_publish setting.

Again, follow the previous instructions to copy the default hook <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/secondary_publish_tk-maya.py to your configuration hooks directory and rename it to alembic_example_secondary_publish.py. Then edit the setting in the configuration to:

hook_secondary_publish: alembic_example_secondary_publish

The app will now use your version of the Publish hook so go ahead and open it up.

The Publish hook is also provided a list of tasks together with a few more inputs:

def execute(self, tasks, work_template, comment, thumbnail_path, 
            sg_task, primary_publish_path, progress_cb, **kwargs):
    ...
  • The comment, thumbnail_path and sg_task represent the information provided by the user through the UI.
  • The primary_publish_path is the path of the primary publish, in this case the scene file itself.

As with the Pre-Publish hook, the default implementation is just a scaffold for iterating over the tasks so the first thing to do is add some code so that it can handle the new alembic_cache output.

To do this, replace:

# publish item here, e.g.
#if output["name"] == "foo":
#    ...
#else:
# don't know how to publish this output types!
errors.append("Don't know how to publish this item!")

with:

# publish alembic_cache output
if output["name"] == "alembic_cache":
    try:
       self._publish_alembic_cache_for_item(item, output, work_template, primary_publish_path, 
                                            sg_task, comment, thumbnail_path, progress_cb)
    except Exception, e:
       errors.append("Publish failed - %s" % e)
else:
    # don't know how to publish this output types!
    errors.append("Don't know how to publish this item!")

Next, add a new publish method to the PublishHook class:

def _publish_alembic_cache_for_item(self, item, output, work_template, primary_publish_path, 
                                    sg_task, comment, thumbnail_path, progress_cb)
    ...

Lets look at what this new method does.

First, it uses the work_template to extract a dictionary of fields from the current scene path:

    scene_path = os.path.abspath(cmds.file(query=True, sn=True))
    fields = work_template.get_fields(scene_path)
    publish_version = fields["version"]

Next, it adds the group name to the fields and then builds the publish path to use for the Alembic Cache file:

    fields["grp_name"] = group_name
    publish_path = publish_template.apply_fields(fields)

Using this path, it then uses the Alembic Cache export command AbcExport to export the group to the publish path:

    frame_start = int(cmds.playbackOptions(q=True, min=True))
    frame_end = int(cmds.playbackOptions(q=True, max=True))
    abc_publish_path = publish_path.replace("\\", "/")
    abc_export_cmd = ("AbcExport -j \"-fr %d %d -root %s -file %s\"" 
                        % (frame_start, frame_end, item["name"], abc_publish_path))
    try:
        self.parent.log_debug("Executing command: %s" % abc_export_cmd)
        mel.eval(abc_export_cmd)
    except Exception, e:
        raise TankError("Failed to export Alembic Cache: %s" % e)

Finally, it registers the published Alembic Cache file with Shotgun:

    self._register_publish(publish_path, ...

And that's it!

This is the complete alembic_example_secondary_publish.py

import os
import shutil
import maya.cmds as cmds
import maya.mel as mel

import tank
from tank import Hook
from tank import TankError

class PublishHook(Hook):
    """
    Single hook that implements publish functionality for secondary tasks
    """    
    def execute(self, tasks, work_template, comment, thumbnail_path, sg_task, primary_publish_path, progress_cb, **kwargs):
        """
        Main hook entry point
        :tasks:         List of secondary tasks to be published.  Each task is a 
                        dictionary containing the following keys:
                        {
                            item:   Dictionary
                                    This is the item returned by the scan hook 
                                    {   
                                        name:           String
                                        description:    String
                                        type:           String
                                        other_params:   Dictionary
                                    }

                            output: Dictionary
                                    This is the output as defined in the configuration - the 
                                    primary output will always be named 'primary' 
                                    {
                                        name:             String
                                        publish_template: template
                                        tank_type:        String
                                    }
                        }

        :work_template: template
                        This is the template defined in the config that
                        represents the current work file

        :comment:       String
                        The comment provided for the publish

        :thumbnail:     Path string
                        The default thumbnail provided for the publish

        :sg_task:       Dictionary (shotgun entity description)
                        The shotgun task to use for the publish    

        :primary_publish_path: Path string
                        This is the path of the primary published file as returned
                        by the primary publish hook

        :progress_cb:   Function
                        A progress callback to log progress during pre-publish.  Call:

                            progress_cb(percentage, msg)

                        to report progress to the UI

        :returns:       A list of any tasks that had problems that need to be reported 
                        in the UI.  Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            task:   Dictionary
                                    This is the task that was passed into the hook and
                                    should not be modified
                                    {
                                        item:...
                                        output:...
                                    }

                            errors: List
                                    A list of error messages (strings) to report    
                        }
        """
        results = []

        # publish all tasks:
        for task in tasks:
            item = task["item"]
            output = task["output"]
            errors = []

            # report progress:
            progress_cb(0, "Publishing", task)

            # publish alembic_cache output
            if output["name"] == "alembic_cache":
                try:
                    self._publish_alembic_cache_for_item(item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb)
                except Exception, e:
                    errors.append("Publish failed - %s" % e)
            else:
                # don't know how to publish this output types!
                errors.append("Don't know how to publish this item!")

            # if there is anything to report then add to result
            if len(errors) > 0:
                # add result:
                results.append({"task":task, "errors":errors})

            progress_cb(100)

        return results

    def _publish_alembic_cache_for_item(self, item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Export an Alembic cache for the specified item and publish it
        to Shotgun.
        """
        group_name = item["name"].strip("|")
        tank_type = output["tank_type"]
        publish_template = output["publish_template"]        

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]

        # update fields with the group name:
        fields["grp_name"] = group_name

        # create the publish path by applying the fields 
        # with the publish template:
        publish_path = publish_template.apply_fields(fields)

        # build and execute the Alembic export command for this item:
        frame_start = int(cmds.playbackOptions(q=True, min=True))
        frame_end = int(cmds.playbackOptions(q=True, max=True))
        # The AbcExport command expects forward slashes!
        abc_publish_path = publish_path.replace("\\", "/")
        abc_export_cmd = "AbcExport -j \"-fr %d %d -root %s -file %s\"" % (frame_start, frame_end, item["name"], abc_publish_path)
        try:
            self.parent.log_debug("Executing command: %s" % abc_export_cmd)
            mel.eval(abc_export_cmd)
        except Exception, e:
            raise TankError("Failed to export Alembic Cache: %s" % e)

        # Finally, register this publish with Shotgun
        self._register_publish(publish_path, 
                               group_name, 
                               sg_task, 
                               publish_version, 
                               tank_type,
                               comment,
                               thumbnail_path, 
                               [primary_publish_path])

    def _register_publish(self, path, name, sg_task, publish_version, tank_type, comment, thumbnail_path, dependency_paths=None):
        """
        Helper method to register publish using the 
        specified publish info.
        """
        # construct args:
        args = {
            "tk": self.parent.tank,
            "context": self.parent.context,
            "comment": comment,
            "path": path,
            "name": name,
            "version_number": publish_version,
            "thumbnail_path": thumbnail_path,
            "task": sg_task,
            "dependency_paths": dependency_paths,
            "published_file_type":tank_type,
        }

        # register publish;
        sg_data = tank.util.register_publish(**args)

        return sg_data

This is the complete tk-multi-publish-alembic-example configuration in the Shot_Step environment.

tk-multi-publish-alembic-example:
  allow_taskless_publishes: true
  display_name: Publish Alembic Example
  expand_single_items: false
  hook_copy_file: default
  hook_post_publish: default
  hook_primary_pre_publish: default
  hook_primary_publish: default
  hook_scan_scene: alembic_example_scan_scene
  hook_secondary_pre_publish: alembic_example_secondary_pre_publish
  hook_secondary_publish: alembic_example_secondary_publish
  hook_thumbnail: default
  location: {name: tk-multi-publish, type: app_store, version: v0.2.7}
  primary_description: Publish and version up the current work file
  primary_display_name: Current Work File
  primary_icon: ''
  primary_publish_template: maya_shot_publish
  primary_scene_item_type: work_file
  primary_tank_type: Maya Scene
  secondary_outputs:
  - description: 'Publish Alembic Cache data for the model'
    display_group: Caches
    display_name: Alembic Cache
    icon: 'icons/alembic_output.png'
    name: alembic_cache
    publish_template: maya_shot_mesh_alembic_cache
    required: false
    scene_item_type: mesh_group
    selected: false
    tank_type: 'Alembic Cache'
  template_work: maya_shot_work

Everything is now setup to publish Alembic Caches for referenced Assets in a Shot scene!

Save the config, reload the app in Maya, open up your test Shot scene and run the Publish Alembic Example command from the menu.

Make sure the Alembic Cache items found by your custom scan hook are selected in the UI, add a comment and hit Publish. The app will first validate that the references are valid using your new pre publish hook. If everything is ok it will then export Alembic Caches and register them as Shotgun published files using your new publish hook!

Follow

18 Comments

  • 0
    Avatar
    Hannes Reindl

    at the moment we are testing around where we should put references and all the other files generated during preproduction and get them into shotgun so yes there is a shot called References and the file is in exactly the location you mentioned we didn't change the tank file structure at all.

    its a bit wierd why the script trys to publish the maya file at all when it should create an alembic cache.

    maybe i did something wrong in the py and yml files but its working so far cause first i forgot to import maya.mel and the publish process succeeded

  • 0
    Avatar
    Hannes Reindl

    of course without exporting an abc file

  • 0
    Avatar
    Alan Dann

    Hi Wesley,

    Just stumbled across your comment whilst doing some work in this area - sorry we missed it before :(

    I don't think it's necessary to replace those characters in the group name as Maya doesn't let you use them in node names.  The only exception is the ':' character which is used in name-spacing so replacing that is probably a good idea...  I'll update the example.

    Thanks

    Alan

  • 0
    Avatar
    David van Heeswijk

    I've been trying to set this up, but as soon as I add the secondary publishes (Step 1)  I get this error:

    ERROR: A general error was reported: while scanning for the next token 

    found character '\t' that cannot start any token 

    I tried reformatting to plain text ( I use Fraise on Mac), but it didn't work.

    I also added the templates in templates.yml, but it didn't make a difference.

    Any idea what might cause this?

     

  • 0
    Avatar
    Alan Dann

    Hi David,

    My guess would be that you have a tab in your shot\_step.yml file which it won't like!

    Make sure you use spaces - your text editor should let you search for \t

    Thanks

    Alan

  • 0
    Avatar
    Michael Wortmann

    Hi,

     

    I installed all scripts butI only get a .ma publish, no .abc :(

     

    Alembic Cache, |group1: Publish failed - Failed to export Alembic Cache: global name 'mel' is not defined

     

    So I guess it comes from these lines in the secondary publish:

                if output["name"] == "alembic_cache":

                    try:

                        self._publish_alembic_cache_for_item(item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb)

                    except Exception, e:

                        errors.append("Publish failed - %s" % e)

     

     

    Any ideas whats wrong?

     

    Michael

     

  • 0
    Avatar
    Michael Wortmann

    Thanks, that was it.

  • 0
    Avatar
    Alan Dann

    Hi Hannes,

    its a bit wierd why the script trys to publish the maya file at all when it should create an alembic cache.

    By default, we always publish the source Maya file in addition to any secondary publishes (e.g. alembic caches) as this is the ground truth that you can always go back to if something else goes wrong.  This can be changed but it requires modifying the various hooks quite extensively.

    maybe i did something wrong in the py and yml files but its working so far cause first i forgot to import maya.mel and the publish process succeeded

    Does that mean it's now working or are you still seeing the error?  If you are still seeing the error then please send over your config and I'll take a look - it might be best to submit a ticket for this as well to make it easier to track.

    Thanks

    Alan

  • 0
    Avatar
    Wesley Elfring

    It might also be nice to do some name validation on the group. For example, make sure the name is OS friendly by stripping the / \ : * ? " < > | characters for windows.

    group_name = item["name"].replace("|", "").replace(":", "").replace("/", "").replace("\", "").replace("\"", "").replace("<", "").replace(">", "")

  • 0
    Avatar
    Patrick Macdonald

    In this example, you mention this tip.

    "Tip: This mechanism allows the association of multiple different outputs with a single item type so if you want to add another output later, for example OBJ export, you can do this without having to modify the scan hook again."

    _Can you provide an example in this context showing how this would actually be implemented? _

    Would this implementation below be the starting point?

    secondary_outputs:
    - description: 'Publish Alembic Cache data for the model'
    display_group: Caches
    display_name: Alembic Cache
    icon: 'icons/alembic_output.png'
    name: alembic_cache
    publish_template: maya_shot_mesh_alembic_cache
    required: false
    scene_item_type: mesh_group
    selected: false
    tank_type: 'Alembic Cache'

    • description: 'Publish OBJ data for the model' display_group: Caches display_name: Obj geometry icon: 'icons/alembic_output.png' name: obj_geo publish_template: maya_shot_obj_geo required: false scene_item_type: mesh_group selected: false tank_type: 'OBJ geometry'  
  • 0
    Avatar
    Josh Tomlinson

    Hi Patrick!

    Yes, I think you're on the right track with your example. The tip you mention could probably be reworded a bit to be clearer, but the idea is that the scan_scene hook can collect items to be output in different ways. So the scene geometry could be exported and published as both an alembic cache and and .obj file. Adding your example secondary output would create an additional task to be processed in the secondary_publish hook. You'd still need to modify the secondary_publish hook, to handle export/publish of mesh_group items with obj outputs (similar to how the mesh_group alembic tasks are handled), but the scan_scene hook wouldn't need to change. 

    I'll talk to the guys internally to see about cleaning up the example a bit and perhaps rewording to make it clearer. I also noticed that the example doesn't match the default config anymore, so we'll take care of that as well. 

    Let me know if you need any more clarification or if you have thoughts on how to make the doc better. 

    Thanks!

    Josh T.

  • 0
    Avatar
    David van Heeswijk

    Hi Alan,

    Yes, copy pasting from this webpage creates tabs apparently. Simetimes the answers are ao easy...

    The error is gone now. I removed the tabs like you said. However, in Maya the Alembic menu doesn't show up yet. When I look in the script editor it says it expects a "required" key in "required".

    In the example it says "false". So I used that. Any clue?

  • 0
    Avatar
    Alan Dann

    Hmm, that's odd

      required: false

    should work fine - is it possible there is another character in there somewhere?  Feel free to attach your configuration and I'll take a look.

    Thanks

    Alan

  • 0
    Avatar
    David van Heeswijk

    I found out what the problem was.

    I placed everything in between {} in the env file and everything worked.

    I discovered an error in the Alembic example tutorial though.

    In the scan scene hook it states:

    items.append({"type":"mesh_group", "name":grp})

    This should be:

    items.append({"type":"mesh_grp", "name":grp})
     

  • 0
    Avatar
    Alan Dann

    Hi David,

    Glad you got it working :)

    Regarding mesh_group vs mesh_grp: the type returned for the item in the scan scene hook should match the scene_item_type defined for the secondary output in your configuration.  

    The example on this page uses mesh_group but I suspect you defined it as mesh_grp in your configuration which is why you had to change it in the scan hook as well - this is fine though, as long as it's consistent it will work.

    Thanks

    Alan

  • 0
    Avatar
    Alan Dann

    Hi Michael,

    Do you have the following at the top of your secondary publish hook:

    import maya.mel as mel

    ?

    (see the complete alembic_example_secondary_publish.py example in the fold-out above)

    Thanks

    Alan

  • 0
    Avatar
    Hannes Reindl

    i have a problem in pre publish, tank keeps telling me its not a valid path, but the path exists and is correct

     

  • 0
    Avatar
    Alan Dann

    Hi Hannes,

    The error means that the path you are trying to publish isn't recognised as a valid work file.  This means that it doesn't match the location or file name convention expected by Toolkit for a Maya work file on disk.

    Unless your configuration is very different to our default configuration, I'd guess that the file being below the References directory is the problem (unless you have a shot called References?).

    You can take any Maya file and save it in the correct location using the Shotgun Save-As command - you should then be able to publish correctly.  I'd recommend trying this to see where Toolkit thinks it should be saving the file to.

    If this still doesn't work then there might be something broken in your configuration so I've included a brief description below on how Toolkit determines the correct location and file name convention for a Maya work file:

    In our default configuration, I would expect the Maya scene to be something like:

    L:\…\sequences\Shot_xyz\prod\work\maya\test.v001.ma

    (where Shot_xyz is the shot name and prod is the step).

    The location and file name format are defined by the template_work setting in the tk-multi-publish app's configuration which for the default configuration is set to the template maya_shot_work.  This in turn is configured to be:

    sequences/{Sequence}/{Shot}/{Step}/work/maya/{name}.v{version}.ma

    in the templates.yml configuration file.

    Does that help?

    Thanks

    Alan

Please sign in to leave a comment.