LookFileBake Output Format Plug-ins

Introduction

The LookFileBakeAPI Python module provides classes and functions that allow developers to implement and register custom output formats for use with LookFileBake nodes, allowing users to write Look Files in custom data formats other than the built-in .klf formats.

Registered LookFileBake output formats are listed as options for the option.outputFormat parameter of LookFileBake nodes.

Katana ships with two built-in output formats: as archive (classic .klf files) and as directory (directory containing pairs of .klf and .attrs files, one pair per pass). These output formats make use of the LookFileBake API internally.

A third output format, as USD, is available as part of the Examples plug-ins (source code also available, see UsdLookFileBake.py). To make this format available for users to choose in LookFileBake nodes, add the path of the Examples folder to the KATANA_RESOURCES environment variable. The USD output format is a basic example that writes .usda files.

Note

The USD LookFileBake output format will only be available if the USD library’s Python modules have been added to the PYTHONPATH environment variable.

LookFileBake API

Module Classes

class LookFileBakeAPI.LookFileBakeSettings(settings=None)

Bases: PyUtilModule.LookFileBakeAPI._BaseSettings

Class representing settings for a Look File bake action.

The following settings are contained in this class:

  • outputPath - The path selected by the user to write to. This can be a file or a directory, depending on the output format plug-in doing the writing.
  • outputFormatName - The name of the output format plug-in doing the writing. This can be passed to GetOutputFormatByName to obtain the registered plug-in class. This name is the same as the BaseLookFileBakeOutputFormat.DisplayName class variable defined by output format plug-ins.
  • sourceFile - The path to the Katana file from which baking is taking place.
  • sourceAsset - The asset ID of the Katana file from which baking is taking place.
__init__(settings=None)

Initializes an instance of the class with the given settings.

class LookFileBakeAPI.LookFilePassData(settings=None)

Bases: PyUtilModule.LookFileBakeAPI._BaseSettings

Class encapsulating the data for a single Look File pass baking action.

The following settings are contained in this class:

  • filePath - The path to the file to which data should be written for this pass. This may be a path to a file inside the directory selected by the user, or a path to a temporary file which will be copied or archived to the final user-selected location.
  • passName - The name of the pass which is being baked. This corresponds to the name of the input port on the LookFileBake node from which the bake was initiated.
  • outputDictList - A list of tuples, where each entry is of the form (overrideDict, rootName, rootType).
  • overrideDict - A dictionary mapping baked locations to opaque identifiers, which are used as keys into sharedOverridesDict, specifying attribute overrides for the location.
  • rootName - The name of the root location being baked.
  • rootType - The type of the root location being baked.
  • materialDict - A dictionary mapping material location paths to a tuple of (locationType, attribute).
  • locationType is the type of the location (usually “material”)
  • attribute is a PyScenegraphAttr describing the material attribute.
  • sharedOverridesDict - A dictionary mapping the opaque identifiers (referenced by the entries in overrideDict, described above) to a dictionary mapping names of attributes to PyScenegraphAttr instances providing the attribute values.
  • rootOverrideDict - A dictionary providing attribute overrides at “/root”, mapping attribute names to PyScenegraphAttr instances providing the attribute values. This is only generated if the includeGlobalAttributes parameter on the LookFileBake node is enabled.
__init__(settings=None)

Initializes an instance of the class with the given settings.

class LookFileBakeAPI.BaseLookFileBakeOutputFormat(settings)

Bases: object

Base class representing a LookFileBake output format. Users wishing to define their own format for Look File baking should inherit from this class and overwrite the following class variables and instance methods.

Class Variables:

  • DisplayName - The name used in the Parameters tab UI to identify the output format.
  • FileExtension - The extension of top level file generated by the output format. For output formats which write passes into a directory, it should be an empty string. This is not appended to the file path value in pass data of writeSinglePass, see PassFileExtension.
  • PassFileExtension - The extension of the individual pass files generated by the output format. This is used for creating the file path provided to pass data in writeSinglePass.

Instance Methods:

  • writeSinglePass - Method to write a single pass of Look File data. Takes a single argument of type LookFilePassData, which provides the information required for the bake operation. Returns a list of files produced by the baking process. The default implementation returns an empty list.
  • postProcess - Optional method to perform any post-processing of the written files. Takes a single argument containing a list of file names written by all passes, and returns a list of file names of post- processed files. The default implementation simply returns the given list of file names.
DisplayName = None
FileExtension = None
PassFileExtension = None
__init__(settings)

Initializes an instance of the class with the given settings.

Parameters:settings (LookFileBakeSettings) – The LookFileBake settings with which to initialise the output format.
postProcess(filePaths)

Performs any post-processing that might be needed after a set of passes have been written.

Return type:list of str
Parameters:filePaths (list of str) – A list of files which have been written so far.
Returns:A list containing any files created by the post-process. The default implementation simply returns filePaths.
writeSinglePass(passData)

Writes a single Look File pass using the current settings and the given pass data.

Return type:list of str
Parameters:passData (LookFilePassData) – The data representing a single Look File pass to be baked.
Returns:A list of paths to files which have been written.

Module Functions

LookFileBakeAPI.GetDefaultOutputFormat()
Return type:BaseLookFileBakeOutputFormat or None
Returns:The default LookFileBake output format, or None if no valid output format has been set.
LookFileBakeAPI.SetDefaultOutputFormat(outputFormat)
Parameters:outputFormat (BaseLookFileBakeOutputFormat) – The output format to set as the default.
LookFileBakeAPI.GetOutputFormats()
Return type:list of BaseLookFileBakeOutputFormat
Returns:A list of the registered output formats.
LookFileBakeAPI.GetOutputFormatNames()
Return type:list of str
Returns:A list of the names of the registered output formats.
LookFileBakeAPI.GetOutputFormatByName(outputFormatName)
Return type:BaseLookFileBakeOutputFormat
Parameters:outputFormatName (str) – The name of the output format to return.
Returns:The output format registered with the given name.
Raises:ValueError – If there is no output format registered with the given name.
LookFileBakeAPI.GetOutputFormatFileExtensions()
Return type:list of str
Returns:A list of file extensions for the registered output formats.
LookFileBakeAPI.RegisterOutputFormat(outputFormat)

Registers a new output format for Look File baking.

Parameters:outputFormat (BaseLookFileBakeOutputFormat) – The output format to register.
Raises:ValueError – If the display name of the output format is already in use by other previously registered output format.
LookFileBakeAPI.UnregisterOutputFormat(outputFormat)

Unregisters an output format.

Parameters:outputFormat (BaseLookFileBakeOutputFormat or str) – The output format, or the display name of the output format to be unregistered.
Raises:ValueError – If the output format cannot be unregistered.

JSON LookFileBake Output Format Example

The JSON LookFileBake output format is a simple example to demonstrate how LookFileBake output formats can be plugged in into Katana.

This format outputs a directory. For each pass, a JSON file containing the pass data will be written into the directory (previously specified by the user).

To make this format available, copy the code below into a Python file inside the Plugins/ directory in one of the configured Katana resources. Alternatively, this code can be executed in a Python tab (note that if the format has been previously registered, it will have to be unregistered with LookFileBakeAPI.UnregisterOutputFormat first).

import json
import os

from Katana import LookFileBakeAPI, PyScenegraphAttr


class JsonLookFileBakeOutputFormat(
        LookFileBakeAPI.BaseLookFileBakeOutputFormat):
    """
    Class implementing a simple JSON LookFileBake output format.
    """

    # Class Variables ---------------------------------------------------------

    DisplayName = "as JSON"
    FileExtension = ""
    PassFileExtension = "json"

    # Instance Methods --------------------------------------------------------

    def writeSinglePass(self, passData):
        """
        @type passData: C{LookFileBakeAPI.LookFilePassData}
        @rtype: C{list} of C{str}
        @param passData: The data representing a single Look File pass to be
            baked.
        @return: A list of paths to files which have been written.
        """
        # Create a JSON document from the given data.
        jsonPassData = {}
        jsonPassData["passName"] = passData.passName
        materialDict = {}
        jsonPassData["materialDict"] = materialDict
        for materialLocation, (locationType, attributes) in \
                passData.materialDict.iteritems():
            materialDict[materialLocation] = {
                "type": locationType,
                "attributes": JsonLookFileBakeOutputFormat.attrToDict(
                    attributes)
            }
        # TODO: Also add passData.outputDictList, passData.rootOverrideDict
        # and passData.sharedOverridesDict.

        # Generate text that will ultimately be written into the text file.
        text = json.dumps(jsonPassData, indent=4)

        # Get the file path for this pass from the given pass data.
        filePath = passData.filePath

        # If the enclosing directory doesn't exist, then try to create it.
        dirPath = os.path.dirname(filePath)
        if not os.path.exists(dirPath):
            os.makedirs(dirPath)

        # Finally write the string containing the pass data into the file.
        with open(filePath, "w") as outFile:
            outFile.write(text)

        return [filePath]

    # Static Methods ----------------------------------------------------------

    @staticmethod
    def attrToDict(attr):
        """
        Helper static method that converts a C{PyScenegraphAttr} attribute into
        a Python dictionary.

        @type attr: C{PyScenegraphAttr.Attr} or C{None}
        @param attr: The attribute to be converted.
        @rtype: C{dict}
        @return: The dictionary representing the given attribute.
        """
        # Early out if not a valid attribute.
        if attr is None:
            return {}

        result = {}
        result["type"] = type(attr).__name__

        if isinstance(attr, PyScenegraphAttr.GroupAttr):
            # Only add if not the default.
            if not attr.getGroupInherit():
                result["groupInherit"] = bool(attr.getGroupInherit())

            # Recursively add children.
            children = {}
            for name, childAttr in attr.childList():
                children[name] = JsonLookFileBakeOutputFormat.attrToDict(
                    childAttr)
            result["children"] = children

        else:
            # Only add if not the default.
            if attr.getTupleSize() != 1:
                result["tupleSize"] = attr.getTupleSize()

            # If only one value, just add it as a scalar. Also, if only samples
            # at 0.0 are available, don't add times; it helps readability.
            samples = attr.getSamples()
            if len(samples) == 1 and samples.keys()[0] == 0.0:
                values = samples[0.0]
                if len(values) == 1:
                    result["value"] = values[0]
                else:
                    result["values"] = list(values)
            else:
                result["samples"] = {}
                for timeSample, values in attr.getSamples().iteritems():
                    if len(values) == 1:
                        result["samples"][str(timeSample)] = values[0]
                    else:
                        result["samples"][str(timeSample)] = list(values)

        return result

# Register the output format.
LookFileBakeAPI.RegisterOutputFormat(JsonLookFileBakeOutputFormat)