Golaem Layout Python API

Golaem Layout is shipped with a Python API module. It is strongly advised to use the API provided by this file to handle Simulation Cache Layout File (.gscl)

Preparing your Environment Variables

The layout API will be reachable if the PYTHONPATH environment variable contains the [Golaem installation directory]/scripts folder

In addition, the PATH environment library must include the [Golaem installation directory]/bin folder : the layout python API requires the glmCrowdIO library to handle licenses

Including Golaem Layout API file in a project

The API needs an app running to be able to manipulate graphs in background, you can insure that by doing:

# Insure that we have an app before calling layout
from glm.Qtpy.Qt import QtWidgets
try:
   app = QtWidgets.QApplication([])
except:
   app = None

Then the Golaem Layout API can be added to a project, by importing the following module:

from glm.layout.layout import *

Finally, a call need to be issued to inform that we are using the layout as a standalone API, before issuing any other layout API call. The call requires the path to the golaem_demo.lic containing directory. This file is used to create a PLE Licenses, thus the licDir path can be ignored if the user is sure to have a valid Lite license, either from Maya Layout or Unreal.

initGolaemStandaloneProduct('C:/Golaem-7.0.3-Maya2018/plug-ins/')

and the following when all layout API calls have been issued

finishGolaemStandaloneProduct()

Using the API to load, modify and save layout files

Load an existing Layout File

It is done by loading a layoutFileHandle from a .gscl file :

layoutFileHandle = openLayoutFile(filePath)

The command takes a string filePath, and returns None on error, or a layoutFileHandle used to modify and save it.

Accessing/Modifying Layout

The cache data can be accessed and modified the following way:

Layout Nodes

listNodeIds(fileHandle) # returns the IDs of all the nodes of a Layout File

Layout Parameters

Layout parameters are parameters generic to the whole file, such as the next available node Id, the root Id of the main graph, the file version, the current file path. 

listLayoutParameters(fileHandle, parameterNameList) # parameterNameList must be an empty list() when calling, which will be fed by the function. Returns False on error
getLayoutParameter(fileHandle, parameterName) # returns None on error or the parameter value
setLayoutParameter(fileHandle, parameterName, parameterValue) # returns False on error

Root ID

Root Id of the main graph, or a group graph if an integer groupNodeId is mentionned, can be get and set via those functions. 

getRootId(fileHandle, groupNodeId=None) # returns -1 on error or the rootId
setRootId(fileHandle, rootId, groupNodeId=None) # returns False on error

Getting Node from ID

getNodeById(fileHandle, nodeID) # returns None on error, or the node instance

Nodes Generic Properties

Some node properties can be set/get by specific functions. All these functions use a node instance, as returned by getNodeById(), or by a creation function createOperator() or createSelector(). On error, getter functions return None while setter functions return False.

Operator and selector shared accessors :

getNodeID(nodeInst) # returns the Node ID
getNodeActive(nodeInst) # returns 1 if enabled, 0 if disabled
getNodeName(nodeInst) # returns the name of the node
getNodePos(nodeInst) # returns an array of [X, Y] value in canvas
setNodeActive(nodeInst, active) # set active to 0 for disabled, or 1 for enabled
setNodeName(nodeInst, name)
setNodePos(nodeInst, pos) # set an array of [X, Y] value in canvas. You can use another node to deduce a position. Default node width in canva is 200 units and separation is an additional 100 units, node height varies depending on type.

Operator only accessors :

getNodeTypeName(nodeInst) # returns the operator type name
getNodeType(nodeInst) # returns the operator numeric type

Selector only accessors :

getNodeEntities(nodeInst) # returns the "entities" string of the selector
setNodeEntities(nodeInst, entities) # sets the "entities" string of the selector

Operator Node Attributes

Operator node attributes depend on the node operator type. Their list can be queried with a function, or the full description of nodes can be found in the [GolaemInstallDir]/scripts/glm/golaem_layoutNodes_definition.json file. Type depends on the attribute, and is always get/set with keyframe and keyValues arrays. Keyframe array can be empty if the attribute is not keyframed. In that occurence, the parameter value will be found in key value between double brackets [[ ]], meaning first value of first (default) frame. For more information about keyFrames and keyValues expected format, see the detailed description of the Simulation Cache Layout File (.gscl)

listNodeAttributes(operatorNode, attributeNameList) # takes an empty attributeNameList list() and feed it, or return False
getNodeAttribute(operatorNode, attributeName, keyFrames, keyValues) # returns None on error
setNodeAttribute(operatorNode, attributeName, keyFrames, keyValues) # returns False on error
setAllNodesAttribute(fileHandle, attributeName, keyFrames, keyValues) # returns False on error
setAllNodesOfTypeAttribute(fileHandle, nodeType, attributeName, keyFrames, keyValues) # returns False on error

Connections

Connections between nodes are requested and handled by those functions. User is responsible to link nodes which are part of the same graph (main graph or a group).

listIncomingConnections(fileHandle, nodeInst, incomingNodeIds) # incomingNodeIds must be an empty list, feed the list or return False
listOutgoingConnections(fileHandle, nodeInst, outgoingNodeIds)  #outgoingNodeIds must be an empty list, feed the list or return False
connect(fileHandle, fromNodeId, toNodeId) # return False on error
disconnect(fileHandle, fromNodeId, toNodeId) # return False on error

Nodes creation

Two methods allow to build new nodes. Nodes can be inserted after other nodes. In that case, a link is automatically done between 'insertAfterNode' and the new node. If the 'insertAfterNode' is root, the "root" is forwarded to the new node. If the new node is the first of a graph (group or main graph), it becomes root automatically. You can refer to the [GolaemInstallDir]/scripts/glm/golaem_layoutNodes_definition.json file for a complete layout nodes definitions.

createSelector(fileHandle, entities, insertAfterNode=None, parentGroupNodeId=None) # returns None on error, or the created selector node instance
listOperators(fileHandle, operatorsList) # feed the operatorsList list() with all the possible operator type names
createOperator(fileHandle, operatorTypeName, insertAfterNode=None, parentGroupNodeId=None) # returns None on error, or the created operator node instance

Nodes deletion

The deletion function takes only a single argument, the node to delete. If the node was the root of its graph, it is the user responsability to set a new root. Deleting a node will also delete all its incoming and outgoing connections.

deleteNode(nodeInstance)

Saving The Layout File

The modified layout can be saved in place, or by specifying a new path. 

saveLayoutFile(fileHandle, newPath = None)

Basic usage sample code

# Insure that we have an app before calling layout (not required if already in a DCC)
from glm.Qtpy.Qt import QtWidgets
try:
   app = QtWidgets.QApplication([])
except:
   app = None
 
# Load module
from glm.layout.layout import *
 
filePath = 'N:/asset/layoutFile.gscl'
fileHandle = openLayoutFile(filePath)
if (fileHandle is not None):
   # get current Root Node Id for main graph
   rootId = getRootId(fileHandle)
   # get current Root Node from Id (to be able to link next nodes)
   previousRootNode = getNodeById(fileHandle, rootId)
   # create a selector, linked after root and automatically set as root instead
   translateSelectorNode = createSelector(fileHandle, "*", previousRootNode)
   # create a Translate operator, linked after selector and automatically set as root instead
   translateOperatorNode = createOperator(fileHandle, "Translate", translateSelectorNode)
   # set the translate attribute of the Translate, no keyframe, a single value [10, 0, 0] in the 1st value of the 1st frame
   setNodeAttribute(translateOperatorNode, "translate", [], [[[10, 0, 0]]])
   saveLayoutFile(fileHandle, filePath)