Skip to content
Steve Theodore edited this page Oct 17, 2016 · 6 revisions

Most of the work you do with streams is filtering: winnowing down a long list of candidates to a shorter one by by checking the members against some kind of test. However there are also a lot of common Maya tasks that require traversing through the Maya scene graph: finding the children of a transform, for example, finding the construction history of a mesh, or finding the bones driven by a constraint are all examples of tasks that swap out the existing stream for new information.

The generic database term for this kind of query is a 'projection' - but that's just a somewhat arbitrary way of saying 'an operation which replaces the contents of a stream with new data based on the existing data'.

get() to change the stream contents

Projection operations are all triggered with the get() function on a stream. For example if you had a stream that contained the names of some camera transforms, you could get the camera shapes themselves like this:

 using('top', 'side', 'persp').get(Children)

The first using() clause on its own will execute as

u'|top', u'|side', u'|persp'

but adding the get() clause will cause the result to become

u'|top|topShape', u'|side|sideShape', u'|persp|perspShape'

In general any get() query will replace the incoming stream with a new stream

append() to add to a stream

Sometimes you'll want to keep the stream you have before transforming it with a projection. In the above example, you might want to keep the camera transforms as well as the camera shapes. The append() function will perform the same operation (since the operator here is Children, that's basically cmds.listRelatives, c=True) and add it on to the stream already there:

 print using('top', 'side', 'persp').append(Children)
 Stream([u'|top', u'|side', u'|persp', u'|top|topShape', u'|side|sideShape', u'|persp|perspShape'])

foreach() to use arbitrary functions

Sometimes you'll want to use some code of your own to transform a stream. The foreach() function applies a one-argument callable to every item in the stream and returns the result, which can be anything the functions returns. An impractical example might be:

print Cameras().short().foreach(lambda p: p.upper()) 
# Stream([u'FRONTSHAPE', u'PERSPSHAPE', u'SIDESHAPE', u'TOPSHAPE'])

A more practical example for PyMel users would be

print Cameras().foreach(pm.PyNode)
Stream([nt.Camera(u'frontShape'), nt.Camera(u'perspShape'), nt.Camera(u'sideShape'), nt.Camera(u'topShape')])

which converts Maya string names into PyNodes. In general, foreach() will be slower than the native minq equivalent: For example, you would prefer Meshes().get(History) to Meshes().foreach(cmds.listHistory) since the former executes only one function call and the latter does one for each item in the stream.


Projection operators

Here are all of the operations which can be used with get() and append():

Operator arguments? flags? Notes
Parents Returns the parents of every item in the stream which has a transform parent
Children Returns the immediate children of every item in the stream which has a transform child
AllParents Returns all of the parents of all items in the stream with parents, up to their root nodes
AllChildren Returns all of the children of all items in the stream (essentially, listRelatives(ad=True))
History y Get the incoming history connections of all items in the stream (= listHistory())
Future y Get the outgoing history connections of all items in the stream (= listHistory(f=True)
Connections y Get the node connections for all items in the stream (= listConnections())
Attribute y Get an attribute string for each item. Pass in the attribute string as an argument
Values If the incoming stream contains attributes (see above), returns a stream of the corresponding values
AttribValues y Combines Attributes and Values into one operation: pass in the attribute name(s) as arguments
WorldPositions Gets the worldspace positions of incoming transforms as tuples.
LocalPositions Gets the local positions of incoming transforms as tuples
LocalAxis Y Y Gets the local x, y or z axis of incoming trandforms. Keyword "local" allows choice between world and local values. Defaults to world values

Attribute

Yields a stream of attribute names for the incoming streams. For example

    Cameras().get(Attribute, 'orthographic')

will produce something like

    Stream([u'topShape.orthographic', u'sideShape.orthographic', ...])

This can be filtered to objects that have actually have the attribute by passing it to an ObjectsOnly:

    Shapes().get(Attributes, 'orthographic').only(ObjectsOnly)

If you pass multiple attributes your stream will expand:

   print using('top').get(Attributes, 'tx', 'ty')
    Stream([u'|top.tx', u'|top.ty'])

Values

Returns all of the values for a stream of attributes (see above). For example

    Transforms().get(Attribute, 'tx').get(Values)

will yield a stream of all the translateX values in the scene. The values will be returned in the same order as the incoming stream (so they can, for example, be turned into a table). If an attribute string in the stream does not exist an exception will be raised.

Note that Values and AttribValues are significantly faster that calling getAttr() in a loop, since all of the queries will execute in one stroke.

AttribValues

Combines a call to Attribute() and Values() into one operation for convenience

 Transforms().get(AttribValues, 'tx')

is equivalent to

 Transforms().get(Attribute, 'tx').get(Values)

Counts

There are several related classes which use the same strategy as AttribValues to get the size of array attributes, particularly commonly used ones like vertex or face counts. Generically they'll look likes this:

 Meshes().get(VertCount)
 #Stream([245, 123, 595,...])

The available count operations are:

#####VertCount Get the vertex counts of a mesh stream

FaceCount

Get the poly face counts of a mesh stream

#####ColorCount Get color vertex count of a mesh stream

#####TweakCount Get the number of tweakss (the .pnts attribuute) on a shape steam

#####CVCount Gets the cv counts on a nurbs stream

#####UVSetCount Gets the count of uv sets in a mesh stream

#####UVPointCount Gets the count of uv vertices in the current uv set of a mesh stream

###Types Returns a stream of tuples (object, nodeType) for every object in the incoming stream. This is mostly useful for tabulating data: to find items by type its more appropriate to use an only() query with a NodeType filter.