cosmogonies.net Blog of cosmogonies.net

handbook
4Apr/120

APyTA_06: Dealing with objects collection.

APyTA_06: Dealing with objects collection.

A lot of time, you will have to iterate through a collection of objects, (Transform, meshes, joints, vertices, etc.).
We already see basic types, and custom-types (class) from Maya. Let's dig into list management:

import pymel.core
for i in range(7): #range return a list of increasing numbers # Result: [0, 1, 2, 3, 4, 5, 6] #
 pymel.core.modeling.polyCube()
theCubeList = pymel.core.general.ls( geometry=True)
print len(theCubeList) #7
print theCubeList[3]._name #|pCube4|pCubeShape4
print theCubeList[-1]._name #|pCube7|pCubeShape7
print theCubeList[9]._name # Error: IndexError: list index out of range #
print theCubeList[2:4] #[nt.Mesh(u'pCubeShape3'), nt.Mesh(u'pCubeShape4')]

So, be really aware of methods that returns a list of objects like ls, you will have to treat them as a list in any cases, emptyList [], or also a singe-item list.
You can access the list items with an index, and use -1 for the last of them.
You also can do a range inside, with this format [startIndex:endIndex:step], and all are optional!

Let's now modify the list:

newCube = pymel.core.modeling.polyCube() #
print len(theCubeList) #7
theCubeList.append(newCube)
print len(theCubeList) #8
del theCubeList[7]
print len(theCubeList) #7

So adding an item its the append() method of the object List, and del to remove an item.
del is a generic statement that allow you to remove from RAM any variables, if you want to free memory yourself.

Sometimes you will want to merge two List (if you use append you will nest your lists).
This can do with the method extend, (or the + operator) :

l1= range(2)
l2= range(2,5)
l1.append(l2)
print l1 #[0, 1, [2, 3, 4]]
l1= range(2)
l2= range(2,5)
l1.extend(l2) #Same as l1 = l1 + l2
print l1 #[0, 1, 2, 3, 4]

If you want to keep an indexed-iterator, you can use 'enumerate' from your list to return both values(your current object and its index)

for i,currentCube in enumerate(pymel.core.general.ls( selection=True)):
  print i, currentCube._name
  if i%2==0: #modulo operator helps here to delete each even index in your list.
    print "Even Index"

Other useful methods are available for list, like sort(), min() or max(), refer to the main doc for the full list.

With Maya 2013 Python API2.0 and also in MotionBuilder, a lot of c++arrays are managed in python as list.
So be very careful, when you iterate through a collection of objects, be REALLY SURE to avoid modifying your list into your loop.
A very famous mistake is to iterate into an object children and into the loop unparent or modify the hierarchy, like this one (in MotionBuilder):


import pyfbsdk
for i in range(10):
  pyfbsdk.FBCreateObject( "Browsing/Templates/Elements", "Cube", "MyCube" )
myGroup = pyfbsdk.FBCreateObject( 'Browsing/Templates/Elements', 'Null', 'GROUP' )

for currentElement in FBSystem().Scene.RootModel.Children:
  print currentElement.Name
  currentElement.Parent = myGroup #This will provoque less iterations than expected !
#Notice here that just even objects are parented...

#Storing the objects into a temp list (objectToParent) will solve this problem:
objectToParent=[]
for currentElement in FBSystem().Scene.RootModel.Children:
  objectToParent.append(currentElement )
for currentElement in objectToParent:
  currentElement.Parent = myGroup
conditions
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.

about
tools
copyright