-
Notifications
You must be signed in to change notification settings - Fork 18
Filters
The most common activity in a minq query is filtering: winnowing a stream down to a more precisely targeted selection on of objects.
There are a couple of distinct types of filtering.
The only()
function of a stream filters by Maya node types. For example
Scene().only(Meshes)
will yield only mesh nodes: it's equivalent to cmds.ls(type=
mesh`)
where
accepts a one-argument callable as an argument. It will call that function on every element in the stream, passing only those values which return a True or truthy value for the filter function. For example:
def has_p(name):
return 'p' in name
print Cameras().get(Parents).where(has_p)
# Stream([u'|persp', u'|top'])
The function can do anything it wants -- the only requirement is that it accepts a single argument. For convenience you can use where_not()
to negate a filter function:
print Cameras().get(Parents).where_not(has_p)
# Stream([u'|front', u'|side'])
For the common case of querying maya node attributes, there's a special syntax that allows you to avoid writing a function just to call and test getAttr
. The minq keyword item
is actually a query factory which creates getAttr
tests for you, so you can write
Cameras().where(item.orthographic == True)
# Result: Stream([u'|front|frontShape', u'|side|sideShape', u'|top|topShape']) #
instead of
def is_ortho(cam):
return cmds.getAttr(cam + ".orthographic")
Cameras().where(is_ortho)
Using item
is also faster than a getAttr
filter function as well: see Atribute Queries for more details.
If you want to narrow to a set of objects which have a certain attribute, the having()
filter will pass only objects which have the attribute in question. This doesn't check the value of the attribute, only it's existence. For example
Shapes().having('orthographic')
# Result: Stream([u'|front|frontShape', u'|persp|perspShape', u'|side|sideShape', u'|top|topShape']) #
having
uses cmds.ls(o=True)
so it's very fast, even compared to an attribute query created with item
.
like()
is used to filter object names as strings. In its simplest form it simply does a case insensitive partial match: if you pass in a sub-string as an argument, it will match any occurrence:
Cameras().like('r')
# Result: Stream([u'|front|frontShape', u'|persp|perspShape']) #
You can however force like to require an exact match by passing the exact
flag. Thus:
Cameras().like('r', exact=True)
# Result: Stream([]) #
# no match because 'r' by itself is not a regex match
# but add in the necessary wildcards...
Cameras().like('.*r.*', exact=True)
# Result: Stream([u'|front|frontShape', u'|persp|perspShape']) #
It's important to remember that by default, minq streams contain full path names, so objects deep in a hierarchy will still be found by like
if one of their parents are! Sometimes that's a very useful feature -- you can find everything under 'r_shoulder' with a single like()
query -- but sometimes it produces false positives. Since like
is a regular expression, however, you can limit matches to the end of a path name using the $
. In this example a plain check on 'arm' would collect hands and fingers because of the path name, but arm$
only collects items which end with "arm".
Joints().like('arm$')
# Result: Stream([u'LeftArm', u'LeftForeArm', u'RightArm', u'RightForeArm']) #
You can use any Python regular expression as an argument; for example Joints().like('spine[24]$')
will find Spine2
and Spine4
but not Spine1
or Spine3
(for a great python regex tester, check out Pythex.org).