LookFileBake Output Format Plug-ins =================================== .. currentmodule:: LookFileBakeAPI 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 `````````````` .. autoclass:: LookFileBakeSettings .. autoclass:: LookFilePassData .. autoclass:: BaseLookFileBakeOutputFormat Module Functions ```````````````` .. autofunction:: GetDefaultOutputFormat .. autofunction:: SetDefaultOutputFormat .. autofunction:: GetOutputFormats .. autofunction:: GetOutputFormatNames .. autofunction:: GetOutputFormatByName .. autofunction:: GetOutputFormatFileExtensions .. autofunction:: RegisterOutputFormat .. autofunction:: UnregisterOutputFormat 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 <#LookFileBakeAPI.UnregisterOutputFormat>`_ first). .. code-block:: python 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)