Open Search
    Substance Library

    Detailed Description

    Since
    R18
    See also
    The Substance Overview article.

    The Substance library contains everything needed to control the Substance Engine integration in Cinema 4D. Main topics are:

    Importing Substance Assets:

    Note
    There's also the command ID_SUBSTANCE_COMMAND_LOADASSET, which may be shorter, if user interaction is wanted.
    void MySubstanceImport()
    {
    if (doc == nullptr)
    return;
    // Setup import parameters
    Filename fn = "some_path/nice_substance.sbsar";
    SUBSTANCE_IMPORT_COPY copyMode = SUBSTANCE_IMPORT_COPY::NO; // do not copy the Substance archive into the project directory and use absolute path to refer to the file
    const Bool errPopup = false; // Don't open any error messages
    const Bool addUndo = true; // Yes, please add an undo step for the import
    const Bool noMaterial = true; // No material will be created on import
    BaseList2D* myImportedAsset = nullptr;
    // Import
    doc->StartUndo(); // DON'T FORGET, mandatory since we chose to add an undo step
    result = ImportSubstance(doc, fn, copyMode, errPopup, addUndo, noMaterial, &myImportedAsset);
    doc->EndUndo(); // DON'T FORGET, mandatory since we chose to add an undo step
    {
    // something went wrong, handle error here...
    return;
    }
    // The substance got successfully inserted into the document
    // ...
    // return;
    }
    BaseDocument * GetActiveDocument()
    Definition: c4d_basedocument.h:497
    Definition: c4d_baselist.h:2245
    Manages file and path names.
    Definition: c4d_file.h:94
    PyObject PyObject * result
    Definition: abstract.h:43
    maxon::Bool Bool
    Definition: ge_sys_math.h:55
    SUBSTANCE_IMPORT_COPY
    Definition: lib_substance.h:280
    @ NO
    Do not copy file to project directory (absolute file path).
    SUBSTANCE_IMPORT_RESULT
    Definition: lib_substance.h:266
    SUBSTANCE_IMPORT_RESULT ImportSubstance(BaseDocument *const doc, const Filename &fn, SUBSTANCE_IMPORT_COPY &copyFile, Bool errPopup, Bool addUndo, Bool createMaterial, BaseList2D **assetPtr)
    const char * doc
    Definition: pyerrors.h:226

    Auto-creating basic material from a Substance:

    void MySubstanceCreateMaterial()
    {
    if (doc == nullptr)
    return;
    if (asset == nullptr)
    {
    // No Substance asset in the scene
    return;
    }
    const Int32 graphIdx = 0; // Use the first graph of the Substance
    const SUBSTANCE_MATERIAL_MODE mode = SUBSTANCE_MATERIAL_MODE::METALLIC; // Use PBR metallic/roughness workflow
    BaseMaterial* const mat = CreateMaterial(myImportedAsset, graphIdx, mode);
    if (mat == nullptr)
    {
    // Failed to create material
    return;
    }
    doc->InsertMaterial(mat);
    }
    Definition: c4d_basematerial.h:28
    const wchar_t * mode
    Definition: fileutils.h:96
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    SUBSTANCE_MATERIAL_MODE
    Definition: lib_substance.h:252
    @ METALLIC
    Create metallic material.
    BaseMaterial * CreateMaterial(BaseList2D *const asset, Int32 graphIndex, SUBSTANCE_MATERIAL_MODE mode)
    BaseList2D * GetFirstSubstance(BaseDocument *const doc)

    Iterate over all graphs, inputs and outputs of a Substance:

    void MyPrintAllSubstances()
    {
    if (doc == nullptr)
    return;
    AutoAlloc<AtomArray> arrSubstances;
    if (arrSubstances == nullptr)
    return;
    const Bool onlySelected = false; // Get all Substances in the document
    GetSubstances(doc, arrSubstances, onlySelected);
    for (Int32 idxSubstance = 0; idxSubstance < arrSubstances->GetCount(); ++idxSubstance)
    {
    BaseList2D* const asset = static_cast<BaseList2D*>(arrSubstances->GetIndex(idxSubstance));
    if (asset == nullptr)
    continue; // This should not happen, but safe is safe
    GePrint("Substance: " + asset->GetName();
    String graphName = "";
    void* lastGraph = nullptr, graph = nullptr;
    while (graph = GetSubstanceGraph(asset, lastGraph, graphName))
    {
    GePrint(" Graph: " + graphName);
    UInt32 inputUid;
    Int32 inputDescId;
    Int32 inputNumElements;
    String inputName;
    void* lastInput = nullptr, input = nullptr;
    GePrint(" Inputs:");
    while (input = GetSubstanceInput(asset, graph, lastInput, inputUid, inputDescId, inputNumElements, inputType, inputName))
    {
    GePrint(" " + inputName + " (" + String::HexToString(inputUid) + ", " + String::IntToString(inputDescId) + ", " + String::IntToString(inputNuMElements) + ", " + String::IntToString((Int32)inputType) + ")");
    lastInput = input;
    }
    UInt32 outputUid;
    String outputName;
    void* lastOutput = nullptr, output = nullptr;
    GePrint(" Outputs:");
    while (output = GetSubstanceOutput(asset, graph, lastOutput, outputUid, outputType, outputName, nullptr))
    {
    GePrint(" " + outputName + " (" + String::HexToString(outputUid) + ", " + String::IntToString((Int32)outputType) + ")");
    lastOutput = output;
    }
    lastGraph = graph;
    }
    }
    }
    void GePrint(const maxon::String &str)
    Definition: ge_autoptr.h:37
    String GetName() const
    Definition: c4d_baselist.h:2412
    Definition: c4d_string.h:39
    static String HexToString(UInt32 v, Bool prefix0x=true)
    Definition: c4d_string.h:478
    static String IntToString(Int32 v)
    Definition: c4d_string.h:495
    Py_ssize_t char * output
    Definition: unicodeobject.h:985
    maxon::UInt32 UInt32
    Definition: ge_sys_math.h:61
    SUBSTANCE_INPUT_TYPE
    Definition: lib_substance.h:292
    SUBSTANCE_OUTPUT_TYPE
    Definition: lib_substance.h:315
    void GetSubstances(BaseDocument *const doc, AtomArray *arr, Bool onlySelected)
    void * GetSubstanceInput(BaseList2D *const asset, void *const graph, void *const prevInput, UInt32 &inputUid, Int32 &firstId, Int32 &numElements, SUBSTANCE_INPUT_TYPE &type, String &name)
    void * GetSubstanceOutput(BaseList2D *const asset, void *const graph, void *const prevOutput, UInt32 &outputUid, SUBSTANCE_OUTPUT_TYPE &type, String &name, BaseBitmap **bmpPtr)
    void * GetSubstanceGraph(BaseList2D *const asset, void *const prevGraph, String &name)

    Changing Substance input parameters:

    This basically works the same as with every other NodeData based entity in Cinema 4D, via SetParameter().

    See also
    SUBSTANCE_INPUT_TYPE
    Warning
    Under no circumstances the BaseContainer of a Substance assets should be accessed directly. The IDs for use with SetParameter() can be obtained via GetSubstanceInput().

    Chapter Substance shader and its parameters:

    The Substance shader has two parameters, SUBSTANCESHADER_ASSET and SUBSTANCESHADER_CHANNEL.

    Groups

     SUBSTANCE_IMPORT_COPY
     
     SUBSTANCE_IMPORT_RESULT
     
     SUBSTANCE_INPUT_TYPE
     
     SUBSTANCE_MATERIAL_MODE
     
     SUBSTANCE_OUTPUT_TYPE
     
     Substance Command IDs
     
     Substance Message IDs
     
     Substance Plugin IDs
     

    Classes

    struct  SubstanceShdGetBitmap
     

    Create

    SUBSTANCE_IMPORT_RESULT ImportSubstance (BaseDocument *const doc, const Filename &fn, SUBSTANCE_IMPORT_COPY &copyFile, Bool errPopup, Bool addUndo, Bool createMaterial, BaseList2D **assetPtr)
     
    BaseMaterialCreateMaterial (BaseList2D *const asset, Int32 graphIndex, SUBSTANCE_MATERIAL_MODE mode)
     
    BaseShaderCreateSubstanceShader (BaseList2D *const asset)
     
    Bool AssignChannelToMaterial (BaseList2D *const asset, Material *const c4dMaterial, Int32 channelId, Int32 outputUid, Bool addUndo)
     

    Get and Insert

    BaseList2DGetFirstSubstance (BaseDocument *const doc)
     
    void GetSubstances (BaseDocument *const doc, AtomArray *arr, Bool onlySelected)
     
    Bool InsertLastSubstance (BaseDocument *const doc, BaseList2D *asset)
     

    Graphs, Inputs, Outputs

    void * GetSubstanceGraph (BaseList2D *const asset, void *const prevGraph, String &name)
     
    void * GetSubstanceInput (BaseList2D *const asset, void *const graph, void *const prevInput, UInt32 &inputUid, Int32 &firstId, Int32 &numElements, SUBSTANCE_INPUT_TYPE &type, String &name)
     
    void * GetSubstanceOutput (BaseList2D *const asset, void *const graph, void *const prevOutput, UInt32 &outputUid, SUBSTANCE_OUTPUT_TYPE &type, String &name, BaseBitmap **bmpPtr)
     

    Preferences

    SUBSTANCE_MATERIAL_MODE PrefsGetMaterialModeSetting ()
     
    Int32 PrefsGetPreviewSetting ()
     

    Misc

    Bool MaterialUsesSubstance (BaseMaterial *const mat)
     
    BaseBitmapGetSubstanceMosaicPreview (BaseList2D *const asset, Int32 w, Int32 h)
     

    Private

    void UpdateImageInputPaths (BaseList2D *const asset, String &path)
     
    void CloneReferencedSubstances (BaseDocument *const doc, BaseShader *const shd, BaseDocument *const ddoc, BaseShader *const dshd)
     
    void CloneReferencedSubstancesObject (BaseDocument *const docSrc, BaseObject *const opSrc, BaseDocument *const docDst, BaseObject *const opDst)
     
    void InsertSubstancePreviewScene (BaseDocument *const doc, BaseList2D *const asset)
     
    const BaseBitmapGetContentBrowserOverlay ()
     

    Function Documentation

    ◆ ImportSubstance()

    SUBSTANCE_IMPORT_RESULT ImportSubstance ( BaseDocument *const  doc,
    const Filename fn,
    SUBSTANCE_IMPORT_COPY copyFile,
    Bool  errPopup,
    Bool  addUndo,
    Bool  createMaterial,
    BaseList2D **  assetPtr 
    )

    Imports a Substance Asset file (.sbsar) into doc.

    Since
    R18
    Parameters
    [in]docThe document to import into.
    [in]fnThe Substance Asset file.
    [in,out]copyFileThe copy file flag: SUBSTANCE_IMPORT_COPY. Determines if Substance Asset files are copied into the project folder (and therefore referenced with relative path).
    If set to SUBSTANCE_IMPORT_COPY::ASK, user's choice will be returned.
    Note: When set to SUBSTANCE_IMPORT_COPY::ASK, the function obviously has to be called in a context, where user interaction is allowed.
    [in]errPopupIf set to true, problems will be communicated to the user with a message requester.
    Note: When set to true, the function obviously has to be called in a context, where user interaction is allowed.
    [in]addUndoIf set to true, an undo step will be added for the import. Caller has to care for the surrounding BaseDocument::StartUndo() and BaseDocument::EndUndo() calls.
    [in]createMaterialSet to true, to have a material created based on the configuration in preferences. Set to false, to suppress any creation of materials.
    [in,out]assetPtrA pointer to a Substance asset pointer. If not nullptr, the pointer to the imported Substance Asset will be returned here.
    Returns
    The result for the import: SUBSTANCE_IMPORT_RESULT

    ◆ CreateMaterial()

    BaseMaterial* CreateMaterial ( BaseList2D *const  asset,
    Int32  graphIndex,
    SUBSTANCE_MATERIAL_MODE  mode 
    )

    Creates a Cinema 4D standard material from asset.

    Since
    R18
    Parameters
    [in]assetThe Substance asset.
    [in]graphIndexThe index of the graph to use (for multi-graph Substances).
    [in]modeThe material creation mode: SUBSTANCE_MATERIAL_MODE
    Returns
    The created material. The caller owns the pointed material.

    ◆ CreateSubstanceShader()

    BaseShader* CreateSubstanceShader ( BaseList2D *const  asset)

    Creates a Substance shader linked to asset.

    Since
    R18
    Parameters
    [in]assetThe Substance asset (may be nullptr).
    Returns
    The created Substance shader. The caller owns the pointed shader.

    ◆ AssignChannelToMaterial()

    Bool AssignChannelToMaterial ( BaseList2D *const  asset,
    Material *const  c4dMaterial,
    Int32  channelId,
    Int32  outputUid,
    Bool  addUndo 
    )

    Creates a Substance shader, links it to asset, sets the Substance output to outputUid and assigns the shader to channelId of c4dMaterial.

    Since
    R18
    Parameters
    [in]assetThe Substance asset, the pointed Substance asset needs to be part of the document.
    [in]c4dMaterialThe Material.
    [in]channelIdThe channel ID: CHANNEL
    [in]outputUidThe unique ID of the Substance output to use.
    [in]addUndoIf set to true, an undo step will be added for the import. Caller has to care for the surrounding BaseDocument::StartUndo() and BaseDocument::EndUndo() calls.
    Returns
    true if successful, otherwise false.

    ◆ GetFirstSubstance()

    BaseList2D* GetFirstSubstance ( BaseDocument *const  doc)

    Retrieves a pointer to the first Substance asset in doc.

    Since
    R18
    Parameters
    [in]docThe document.
    Returns
    The first Substance asset or nullptr, if none exists. Cinema 4D owns the pointed Substance asset.

    ◆ GetSubstances()

    void GetSubstances ( BaseDocument *const  doc,
    AtomArray arr,
    Bool  onlySelected 
    )

    Retrieves all (or only selected) substances assets doc.

    Since
    R18
    Parameters
    [in]docThe document.
    [in]arrThe AtomArray to fill. The caller owns the pointed array.
    [in]onlySelectedSet to true to get only selected Substance assets.

    ◆ InsertLastSubstance()

    Bool InsertLastSubstance ( BaseDocument *const  doc,
    BaseList2D asset 
    )

    Inserts asset into doc (as last element).

    Since
    R18
    Parameters
    [in]docThe document.
    [in]assetThe Substance asset. On success Cinema 4D takes over the ownership of the pointed Substance asset.
    Returns
    true if success, otherwise false.

    ◆ GetSubstanceGraph()

    void* GetSubstanceGraph ( BaseList2D *const  asset,
    void *const  prevGraph,
    String name 
    )

    Retrieves the Substance graph. This function may be used to iterate over the graphs of asset.

    Since
    R18
    Parameters
    [in]assetThe Substance asset.
    [in]prevGraphPass nullptr to get the first graph, pass a graph pointer to get the following graph.
    [out]nameName of the returned graph. Only valid if return value != nullptr.
    Returns
    A pointer to identify the graph, may not be dereferenced. nullptr if graph is not available. Cinema 4D owns the pointed graph.

    ◆ GetSubstanceInput()

    void* GetSubstanceInput ( BaseList2D *const  asset,
    void *const  graph,
    void *const  prevInput,
    UInt32 inputUid,
    Int32 firstId,
    Int32 numElements,
    SUBSTANCE_INPUT_TYPE type,
    String name 
    )

    Retrieves a Substance input of an asset. This function may be used to iterate over the inputs of a graph of asset.

    Since
    R18
    Parameters
    [in]assetThe Substance asset.
    [in]graphThe graph.
    [in]prevInputPass nullptr to get the first input, pass an input pointer to get the following input.
    [out]inputUidThe unique ID of the input. Only valid if return value != nullptr.
    [out]firstIdThe ID of the first component of the input parameter in Cinema 4D (see also numElements). This ID can be used to create a DescID for C4DAtom::SetParameter(). Only valid if return value != nullptr.
    [out]numElementsThe number of description elements used in Cinema 4D to represent the Substance input parameter. Only valid if return value != nullptr.
    [out]typeThe data type of the input: SUBSTANCE_INPUT_TYPE. Only valid if return value != nullptr.
    [out]nameName of the returned input. Only valid if return value != nullptr.
    Returns
    A pointer to identify the input, may not be dereferenced. nullptr if input is not available. Cinema 4D owns the pointed input.

    ◆ GetSubstanceOutput()

    void* GetSubstanceOutput ( BaseList2D *const  asset,
    void *const  graph,
    void *const  prevOutput,
    UInt32 outputUid,
    SUBSTANCE_OUTPUT_TYPE type,
    String name,
    BaseBitmap **  bmpPtr 
    )

    Retrieves a Substance input of an asset. This function may be used to iterate over the outputs of a graph of asset.

    Since
    R18
    Parameters
    [in]assetThe Substance asset.
    [in]graphThe graph.
    [in]prevOutputPass nullptr to get the first output, pass an output pointer to get the following output.
    [out]outputUidThe unique ID of the output. Only valid if return value != nullptr.
    [out]typeThe output type ID. Only valid if return value != nullptr.
    [out]nameThe name of the returned output. Only valid if return value != nullptr.
    [in,out]bmpPtrA pointer to a BaseBitmap pointer. If not nullptr, a pointer to a clone of the output channel bitmap will be returned here. The caller owns the pointed BaseBitmap.. Only valid if return value != nullptr.
    Returns
    A pointer to identify the output, may not be dereferenced, Cinema 4D owns the pointed output., or nullptr if output is not available

    ◆ PrefsGetMaterialModeSetting()

    SUBSTANCE_MATERIAL_MODE PrefsGetMaterialModeSetting ( )

    Convenience function to get the material creation mode set in Substance preferences.

    Since
    R18
    Returns
    The material creation mode: SUBSTANCE_MATERIAL_MODE

    ◆ PrefsGetPreviewSetting()

    Int32 PrefsGetPreviewSetting ( )

    Convenience function to get the preview mode for Content Browser set in Substance preferences.

    Since
    R18
    Returns
    Zero for mosaic preview, otherwise rendered preview scene.

    ◆ MaterialUsesSubstance()

    Bool MaterialUsesSubstance ( BaseMaterial *const  mat)

    Checks if mat contains any Substance shaders.

    Since
    R18
    Parameters
    [in]matThe material to check for Substance shaders.
    Returns
    true if the material uses a Substance shader, otherwise false.

    ◆ GetSubstanceMosaicPreview()

    BaseBitmap* GetSubstanceMosaicPreview ( BaseList2D *const  asset,
    Int32  w,
    Int32  h 
    )

    Returns an image with previews of the output channels of asset.

    Since
    R18
    Note
    While the Substance asset won't have to be re-rendered, this operation still involves downscaling of all Substance outputs.
    Parameters
    [in]assetThe Substance asset.
    [in]wThe width of the preview image.
    [in]hThe weight of the preview image.
    Returns
    A pointer to the resulting bitmap. The caller owns the pointed BaseBitmap.

    ◆ UpdateImageInputPaths()

    void UpdateImageInputPaths ( BaseList2D *const  asset,
    String path 
    )

    Private.

    Since
    R18

    ◆ CloneReferencedSubstances()

    void CloneReferencedSubstances ( BaseDocument *const  doc,
    BaseShader *const  shd,
    BaseDocument *const  ddoc,
    BaseShader *const  dshd 
    )

    Private.

    Since
    R18

    ◆ CloneReferencedSubstancesObject()

    void CloneReferencedSubstancesObject ( BaseDocument *const  docSrc,
    BaseObject *const  opSrc,
    BaseDocument *const  docDst,
    BaseObject *const  opDst 
    )

    Private.

    Since
    R18

    ◆ InsertSubstancePreviewScene()

    void InsertSubstancePreviewScene ( BaseDocument *const  doc,
    BaseList2D *const  asset 
    )

    Private.

    Since
    R18

    ◆ GetContentBrowserOverlay()

    const BaseBitmap* GetContentBrowserOverlay ( )

    Returns the Substance logo bitmap. Private.

    Since
    R19
    Returns
    The logo bitmap. Cinema 4D owns the pointed BaseBitmap.