Load camera image plane in Maya

Next, we implement a custom camera loader within Maya that loads a reviewable Quicktime (.mov) as an image plane, to aid animation and lighting framing.

Constrain camera loader

As a preparation, we constrain the camera loader to only be seen when on animation and lighting tasks, hiding it during modelling. We do this by modifying the loader definition json and adding the discoverable key:

mypipeline/ftrack-connect-pipeline-definitions/resource/definitions/loader/maya/camera-maya-loader.json

1{
2    "type": "loader",
3    "name": "Camera Loader",
4    "asset_type": "cam",
5    "host_type": "maya",
6    "ui_type": "qt",
7    "discoverable": ["animation","lighting"]
8
9}

Here we have added the additional discoverable key with associate task type names.

Render loader

This serves as an example on how to implement your own loader that is not part of the framework but required in production.

Definition

Reviewable Quicktimes are most likely published with render (asset type), from Nuke Studio or similar tool. This is why we implement an new render loader definition:

mypipeline/ftrack-connect-pipeline-definitions/resource/definitions/loader/maya/render-maya-loader.json

 1{
 2  "type": "loader",
 3  "name": "Render Loader",
 4  "asset_type": "render",
 5  "host_type": "maya",
 6  "ui_type": "qt",
 7  "contexts": [
 8    {
 9      "name": "main",
10      "stages": [
11        {
12          "name": "context",
13          "plugins":[
14            {
15              "name": "context selector",
16              "plugin": "common_passthrough_loader_context",
17              "widget": "common_default_loader_context"
18            }
19          ]
20        }
21      ]
22    }
23  ],
24  "components": [
25    {
26      "name": "movie",
27      "file_formats": [".mov", ".r3d", ".mxf", ".avi"],
28      "stages": [
29        {
30          "name": "collector",
31          "plugins":[
32            {
33              "name": "Collect components from context",
34              "plugin": "common_context_loader_collector"
35            }
36          ]
37        },
38        {
39          "name": "importer",
40          "plugins":[
41            {
42              "name": "Import reviewable to Maya",
43              "plugin": "maya_render_loader_importer",
44              "options": {
45                "camera_name": "persp"
46              }
47            }
48          ]
49        },
50        {
51          "name": "post_importer",
52          "plugins":[
53            {
54              "name": "maya",
55              "plugin": "common_passthrough_loader_post_importer"
56            }
57          ]
58        }
59      ]
60    }
61  ],
62  "finalizers": [
63    {
64      "name": "main",
65      "stages": [
66        {
67          "name": "pre_finalizer",
68          "visible": false,
69          "plugins":[
70            {
71              "name": "Pre finalizer",
72              "plugin": "common_passthrough_loader_pre_finalizer"
73            }
74          ]
75        },
76        {
77          "name": "finalizer",
78          "visible": false,
79          "plugins":[
80            {
81              "name": "Finalizer",
82              "plugin": "common_passthrough_loader_finalizer"
83            }
84          ]
85        },
86        {
87          "name": "post_finalizer",
88          "visible": false,
89          "plugins":[
90            {
91              "name": "Post finalizer",
92              "plugin": "common_passthrough_loader_post_finalizer"
93            }
94          ]
95        }
96      ]
97    }
98  ]
99}

Definition breakdown:

  • name; We follow the Framework naming convention here.

  • asset_type: Change here if quicktimes are published onto a different custom asset type than render.

  • component name; The name of loadable components on an asset version.

  • component file formats/types; List of file format extensions supported by the loader plugin.

  • importer plugin; Here we reference the new maya_render_loader_importer that we are about to write.

  • importer plugin options; In the options we expose a camera_name attribute, which will be an option that the user can change.

Render importer plugin

Finally we implement a new importer plugin:

mypipeline/ftrack-connect-pipeline-definitions/ftrack-connect-pipeline-definition/resource/plugins/maya/python/loader/importers/maya_render_loader_importer.py

 1# :coding: utf-8
 2# :copyright: Copyright (c) 2014-2022 ftrack
 3
 4import maya.cmds as cmds
 5
 6from ftrack_connect_pipeline_maya import plugin
 7import ftrack_api
 8
 9
10class MayaRenderLoaderImporterPlugin(plugin.MayaLoaderImporterPlugin):
11    '''Maya Quicktime importer plugin'''
12
13    plugin_name = 'maya_render_loader_importer'
14
15    def run(self, context_data=None, data=None, options=None):
16        '''Load alembic files pointed out by collected paths supplied in *data*'''
17
18        results = {}
19
20        camera_name = options.get('camera_name', 'persp')
21        paths_to_import = []
22        for collector in data:
23            paths_to_import.extend(collector['result'])
24
25        for component_path in paths_to_import:
26            self.logger.debug(
27                'Importing path "{}" as image plane to camera "{}"'.format(
28                    component_path, camera_name
29                )
30            )
31            imagePlane = cmds.imagePlane(
32                camera=camera_name, fileName=component_path
33            )
34            cmds.setAttr('{}.type'.format(imagePlane[0]), 2)
35            cmds.setAttr('{}.useFrameExtension'.format(imagePlane[0]), True)
36
37            self.logger.info(
38                'Imported "{}" to {}.'.format(component_path, imagePlane[0])
39            )
40
41            results[component_path] = imagePlane[0]
42
43        return results
44
45
46def register(api_object, **kw):
47    if not isinstance(api_object, ftrack_api.Session):
48        # Exit to avoid registering this plugin again.
49        return
50    plugin = MayaRenderLoaderImporterPlugin(api_object)
51    plugin.register()

Plugin breakdown:

  • plugin_name; The name of the plugin, have to match the name used within the definition.

  • run function; The function that will be run during load in the ftrack Assembler.

Custom publisher plugin

Writing a custom publisher is very similar to writing a loader, the big difference is that you also will have to write a publisher collector that collects which objects within the DCC to publish, and also decide on component name and file format extension.

In this tutorial, we will not provide any example publisher code. Instead we refer to the extensive set of built-in publishers for inspiration.