Houdini Engine for Maya
 All Files Pages
Scripting

Plugin Commands

There are two native plugin commands, houdiniAsset and houdiniEngine

houdiniEngine

houdiniEngine [-license] [-houdiniVersion] [-houdiniEngineVersion] [-buildHoudiniVersion] [-buildHoudiniEngineVersion] [-makeTempDir] [-saveHIP string]

Long Name Argument Description
-license (-lic) Returns the license type that is currently in use
-houdiniVersion (-hv) Returns the houdini version that is currently in use
-houdiniEngineVersion (h-ev) Returns the houdini engine version that is currently in use
-buildHoudiniVersion (-bhv) Returns the houdini version that was built with
-buildHoudiniEngineVersion (-bev) Returns the houdini engine version that was build with
-makeTempDir (-mtp) Returns the path of the houdini temp directory, creating it if needed
-saveHIP (-sh) filePath Save the contents of the engine session to the specified hip file


// Some Examples:

houdiniEngine -lic;
// Result: Houdini-Engine // 
houdiniEngine -hv;
// Result: 17.0.354//
houdiniEngine -makeTempDir;
// Result: /usr/tmp/houdini_temp // 


houdiniAsset

houdiniAsset [-listAssets string] [-loadAsset string string] [-resetSimulation string ] [-cookMessages string ] [-reloadAsset string] [-reloadNoSync string] [-sync string] [-syncAttributes] [-syncOutputs] [-syncHidden] [-syncTemplatedGeos] [-autoSyncId string]

Long Name Argument Description
-listAssets (-ls) filePath Returns a string array of the names of assets contained in this hda
-loadAsset (-la) filePath assetName Load the named asset from this hda
-resetSimulation(-rs) assetNode reset the simulation for the asset node
-cookMessages(-cm) assetNode Returns the cook status for the most recent cook for the asset node
-reloadAsset(-rl) assetName reload the asset definition for the specified asset, from the hda from which it was previously loaded
-reloadNoSync(-rn) assetName reload the asset definition for the specified asset, from the hda from which it was previously loaded, but do not sync the asset after reloading. If you know that the asset has the same number and types of outputs as before, this avoids deleting and rebuilding the output shapes in Maya, and any downstream modifications to the outputs will be preserved.
-sync(-syn) assetNode sync the asset node
-syncAttributes(-sa) if the -sync flag is present, sync only the attributes, not the outputs for the specified asset noded
-syncOutputs(-so) if the -sync flag is present, sync only the outputs, not the attributes
-syncHidden(-shi) when syncing attributes, create attributes for the hidden parms as well
-syncTemplatedGeos(-stm) when syncing outputs, sync templated geos
-autoSyncId(-asi) assetNode Returns the current autoSyncId for this asset, used internally to determine whether there is already an autoSync running, or whether another one should be triggered


// Some Examples:

houdiniAsset -listAssets "/home/julia/houdini17.0/otls/extrudeFaces.hda";
// Result: Object/extrudeFaces //

houdiniAsset -loadAsset "/home/myHomeDir/houdini17.0/otls/extrudeFaces.hda" "Object/extrudeFaces";
// Result: |extrudeFaces1 //

houdiniAsset -sync |extrudeFaces1 -syncOutputs;


Mel Procs

There are a number of global mel procs in the houdiniEngine module. Many of these were put in place to support functionality that is available from the menu, from attribute editor buttons, or from one of the shelves. Only the ones that seem usable for general purpose scripting have been documented here.

Loading and Connecting Assets

  • houdiniEngine_loadAssetLibrary(string $assetLibraryFilePath)
    Load the asset definitions from the asset library (hda)
  • houdiniEngine_loadAsset(string$assetLibraryFilePath, string $asset)
    Instantiate the named asset, loading the specified asset library if needed
  • houdiniEngine_loadAndAddAsset(string $assetFile, string $assetName, string $assignMode)
    load the asset, and attach it to the selected Maya objects according to the $assignMode:
    OPERATOR_SINGLE: connect all the selected objects to the first input.
    OPERATOR_MULTI: connect selected items to inputs in selection order.
    HISTORY: connect to the first selected item as construction history
  • houdiniEngine_autoSyncAssetOutput(string $assetNode, int $autoSyncId)
    check that no other autosync is running, and then sync
  • houdiniEngine_setAssetInput(string $inputAttr, string $objects[])
    assign the objects to to the specified input attribute, merging if necessary
  • houdiniEngine_syncAssetOutput(string $assetNode)
    rebuild the assets output nodes
  • houdiniEngine_syncAsset(string $assetNode)
    sync attributes and outputs
  • houdiniEngine_syncSelectedAsset()
    sync the asset nodes on the selection list
  • houdiniEngine_reloadSelectedAssets()
    reload the asset definition for the selected assets. Note that other nodes using the same asset definition will not update until forced to cook (and then sync)
  • houdiniEngine_getAssetInput(string $inputAttr)
    get all the input nodes connected to the asset node
  • houdiniEngine_getDownstreamAssets( string $inputNode)
    get all the asset nodes immedialtely downstream of the input node
  • houdiniEngine_getSelectedAssetNodes()
    get all the houdini input nodes upstream of the asset
  • houdiniEngine_updateShelf()
    replace the contents of your local Houdini shelf with the version from the current install
  • houdiniEngine_updateToolsShelf()
    rebuild the content of the tools shelf from the contents of the Tools directory in your current engine instll
  • houdiniEngine_buildToolsShelf(string $toolsLocation)
    rebuild the content of the tools shelf from the contents of the specified directory. So you can replace the tools with your own aversions, or add additional tools. Any new tools need to have the corresponding .json file created.

Construction History

  • houdiniEngine_addHistory($assetNode)
    add the assetNode as construction history to the selected mesh, (or to the mesh whose components are selected)
  • houdiniEngine_addSelectedHistory()
    determine if there is a suitable asset node selected, and if there is apply it to the selected mesh
  • houdiniEngine_bakeAsset($assetNode)
    bake the specified asset
  • houdiniEngine_connectHistory(string $inputAttr, string $objects[], string $components[])
    connect the objects to the input attr as history
  • houdiniEngine_deleteHistory(string $node)
    Delete construction history, including any asssets, from this node. (The regular Maya delete History does not cross plugin nodes)
  • houdiniEngine_removeHistory(string $assetNode)
  • houdiniEngine_removeSelectedHistory()

Procs for ScriptJobs

These two procs are used in script jobs to make sure object level shader changes propagate to the output geometry.

  • houdiniEngine_objectShaderChanged()
    For all meshes connected to input geometry nodes, checks if the object shader assigned to a mesh is the same as the one listed on its input geometry node, if it isn't reset it and dirty the input. We use this with a connectionChanged event to track when shader assignment changes on input geometry. It could be used diretcly to update the shader information on all the input geometry nodes.
  • houdiniEngine_shaderChangeCallbacks()
    For all meshes connected to input geometry nodes, set up the shader changed script job on file open.

Houdini Pages and Applications

These mel procs will start start an application or open a web page

  • houdiniEngine_saveHipFile()
  • houdiniEngine_viewInHoudini()
  • houdiniEngine_runHKey()
  • houdiniEngine_launchChangeLog()
  • houdiniEngine_launchForum()
  • houdiniEngine_launchGitHub()
  • houdiniEngine_launchOrboltPageClick()
  • houdiniEngine_launchSubmitBugs()
  • houdiniEngine_onlineDocumentation()

Callbacks

The asset node allows you to register preSync and postSync callbacks by setting the preSyncCallback or postSyncCallback attribute on the asset to the name of the callback script e.g:

setAttr -type "string" myAssetNode.preSyncCallback "myPreSyncCallback";

Callbacks should be of the form:

preSync(string $assetNode, int $syncOnlyAttributes, int $syncOnlyOutputs)
postSync(string $assetNode, int $syncOnlyAttributes, int $syncOnlyOutputs)

These callbackes are intended to allow saving modifications that were made to the asset's attributes or outputs so that they can be reapplied after the asset is synced. For example, you might want to change the lock state of parm attributes, or rename output nodes to be consistent with local naming conventions

// These procs let you cache which parm attributes have been hidden in the channel box
// and restore the hidden state after a sync

global string $parmAttrNames[];

global proc preSync(string $assetNode, int $syncOnlyAttributes, int $syncOnlyOutputs) {
    global string $parmAttrNames[];
    
    // in real life, this should recurse to all the leaf children
    // and handle multi attributes appropriately, but this is the simple example
    
    string $parmAttrs[] = `attributeQuery -node $assetNode  -lc "houdiniAssetParm"`;
    clear $parmAttrNames;
    for($parmAttr in $parmAttrs) {
        if  ( !`getAttr -channelBox  (  $assetNode + "." + $parmAttr )`) {
             $parmAttrNames[size($parmAttrNames)] = $parmAttr;
        }
    }
}

global proc postSync(string $assetNode, int $syncOnlyAttributes, int $syncOnlyOutputs)
{
    global string $parmAttrNames[];
   
    for($parmAttr in $parmAttrNames) {
         if( `attributeExists $parmAttr $assetNode`) {
            setAttr -channelBox off (  $assetNode + "." + $parmAttr );
        }
    }
}


// This proc shows how to give a unique custom name to all your output meshes

global proc postSyncRename(string $assetNode, int $syncOnlyAttributes, int $syncOnlyOutputs)
{
    // Here's an example that looks for output meshes and renames the mesh and its parent transform
    // The # in the name will force it to resolve to a unique node name

    if($syncOnlyAttributes)
        return;
    
    string $baseName = "customName#";

    // we only want the meshData connections, but listConnections gets confused
    // trying to access a single compound child across all elements of a multi
    string $outputObjCon[] = `listConnections -p on ($assetNode + ".outputObjects")`;
    string $outputMeshCon[];
    for($con in $outputObjCon) {
        string $src = `connectionInfo -sfd $con`;
        // if a mesh output has auxiliary nodes or downstream history
        // need a temporary mesh shape to backstop the history
        if(endsWith($src, "outputPartMeshData")) {
            $outputMeshCon[size($outputMeshCon)] = $con;
        }
    }
    
    for($con in $outputMeshCon) {
        string $outNode = plugNode($con); 
            
        if(nodeType($outNode) == "mesh") {
            // renaming the Xform will rename the shape as well;
            string $outXforms[] = `listRelatives -parent -path $outNode`;
            rename $outXforms[0] $baseName;
        } else {
            // if there were groups on the output mesh
            // there will be groupParts nodes in between the  hda and the output mesh
            // list connections returns the name of a non-dag node
            // and the shortest unique substring of the path of dag node
            // since we didn't specify shape, we get the transform of the mesh
            // which is what we wanted to rename anyway
            while(nodeType($outNode) == "groupParts") {
                string $cons[] = `listConnections ($outNode + ".outputGeometry")`;
                $outNode = $cons[0];
            }
            if(nodeType($outNode) == "transform") {
                rename $outNode $baseName;
            }
        }
    }
}


Python

import maya.cmds as cmds
import maya.mel as mel

# load the plugin
cmds.loadPlugin("houdiniEngine")

# load the Maya scene
cmds.file("/tmp/test_sphere.mb", open=True, force=True)

# load the Houdini asset
asset = cmds.houdiniAsset(loadAsset=["/tmp/test_asset.hda", "Sop/test_asset"])

# speicfy the input geometries to be connectd to the asset
input_geos = [ "|pSphere1" ]

# construct a single string that represent a MEL string array
# wrap with { }
mel_string_array = "{{ {} }}".format(
    # separate by comma
    ", ".join(
        # quote each string
        ["\"{}\"".format(s) for s in input_geos]
        )
    )

# source MEL script for houdiniEngine_setAssetInput
cmds.eval("source houdiniEngineAssetInput")

# call MEL function to connect input geometry
# connect to an actual node input
mel.eval("houdiniEngine_setAssetInput {} {}".format(
    asset + ".input[0].inputNodeId",
    mel_string_array
    ))

# connect to an oppath parameter that accepts geometry
mel.eval("houdiniEngine_setAssetInput {} {}".format(
    asset + ".houdiniAssetParm.houdiniAssetParm_objpath1__node",
    mel_string_array
    ))

# call setAttr to set some attribute
cmds.setAttr("{}.houdiniAssetParm.houdiniAssetParm_height".format(asset), 2)

# to "click" a button that does not affect output geometry, use setAttr
cmds.setAttr("{}.houdiniAssetParm.houdiniAssetParm_some_button__button".format(asset), 1)
# may need to call dgeval() to force the click to be processed
cmds.dgeval("{}.output".format(asset))

# source MEL script for houdiniEngine_syncAssetOutput
mel.eval("source houdiniEngineAssetSync")

# sync the asset if needed
mel.eval("houdiniEngine_syncAssetOutput {}".format(asset))