Substance Designer - output node metadata get/set

This comes from the Adobe discord when I asked how to get/set metadata on the output nodes of a graph (so I could set an “exportable” kvp on it for an export tool)

The metadata on outputs is really weird, technically it’s stored at the graph level rather than on the node. If you get its output property then use that as an ID in the graph you should be able to get the metadata and then add to or query it as desired. Once you have that metadata object you should be able to metadata.setPropertyValueFromId('key', SDValueString.sNew('value') or get the value from its ID.

propertyOut = sdNodeOutput.getProperties(SDPropertyCategory.Output)[0]
metadata = sdGraph.getPropertyMetadataDictFromId(propertyOut.getId(), SDPropertyCategory.Output)

With this in mind I’ve made these simple functions that can likely be reused fairly easily :slight_smile:

import sd
from sd.api import SDValueString
from sd.api.sdproperty import SDPropertyCategory
ctx = sd.getContext()
app = ctx.getSDApplication()
uiMgr = app.getQtForPythonUIMgr()

def curr_graph():
    graph = uiMgr.getCurrentGraph()
    return graph

def get_all_metadata_from_node(sdNodeOutput):
    """Get the metadata object from a given output node

        sdNodeOutput (SDSBSCompNode): output node to get metadata from

        SDMetadataDict: metadata object from node
    propertyOut = sdNodeOutput.getProperties(SDPropertyCategory.Output)[0]
    metadata = curr_graph.getPropertyMetadataDictFromId(
        propertyOut.getId(), SDPropertyCategory.Output
    return metadata

def get_metadata_value_from_node(sdNodeOutput, key):
    """Try to get the metadata value from a given node and key

        sdNodeOutput (SDSBSCompNode): output node to check for metadata on
        key (str): key of metadata object

        str, None: If key is found, return value else None
    metadata = get_all_metadata_from_node(sdNodeOutput)
        return metadata.getPropertyValueFromId(key).get()
        # bare except as we just want it to not error if it doesn't find anything
        # or "invalidArgument" is passed - which it shouldn't
            f"Key: {key} not found in metadata of "
    return None

def set_metadata_on_node(sdNodeOutput, key, value):
    """Given a node and key/value - set it on the node's metadata object

        sdNodeOutput (sdNode): Node to set data on
        key (str): key to store
        value (str): value (as string) to set
    metadata = get_all_metadata_from_node(sdNodeOutput)
    metadata.setPropertyValueFromId(key, SDValueString.sNew(value))

Figured it was worth sharing and having somewhere online

1 Like