Joint Lists?

So is there any function or method call that would return a list of all the models joints? It is really annoying haveing to grab all of the joints individually.

My second question: Is there any method or function call that would return the name of the joint as it is named in the EGG file?


jointName = jointNode.getName()
print jointName

And the output would come out as Leg_r_upper?

You can call:


actor.listJoints()

to output a hierarchical list of all the joints to the console window. If you actually want to walk through the list of joints and return them one at a time to Python, so that you operate on them (for instance, to expose every joint), you’ll have to write a recursive function to do it, something like this:

def getParts(part):
  parts = []
  parts.append(part)
  for i in range(part.getNumChildren()):
    parts += getParts(part.getChild(i))
  return parts

And then you can invoke this function with the top “part” of your Actor, like this:


getParts(actor.getPart('modelRoot').node().getBundle())

Note that an Actor internally maintains a hierarchy of “parts”, which include the joints (CharacterJoint) and sliders (MovingPartBase) as well as some ordinary PartGroup objects that just glue together the hierarchy. This hierarchy of parts is not related to the hierarchy of scene graph nodes.

Each part has a name, which you can query with getName(). In the case of a joint, this will be the same name that appears in an egg file. Of course, in the case of an exposed joint, the name is copied to the PandaNode that is created to expose the joint; and this name is also the name that appears in the egg file.

David

Wow thanks.

Umm how exactly do I use the listJoints() function? Because I am getting and error message saying that Actor object has no attribute listJoints


self.joints = self.pilot.listJoints()

That is the method call I use.

Also, I have been playing around with the function that you provided and I cannot seem to gain control of each joint I keep on getting a Nonetype Error


self.trye = self.getParts(self.pilot.getPart('modelRoot').node().getBundle())
  
  for x in self.trye:
   print x.getName()
   if(x.getName != "pilot" or x.getName != "<skeleton>"):
    y = self.pilot.controlJoint(None, 'modelRoot', x.getName())
    y.setHpr(0,0,0)

that is the code.

Actor.listJoints() is only defined as of Panda3D version 1.2. Even then, it has no return value; it simply lists the joints to the console window.

As to your loop, you probably meant to write a statement like this:


if(x.getName() != "pilot" and x.getName() != "<skeleton>"):

Instead of this:


if(x.getName != "pilot" or x.getName != "<skeleton>"):

But it might be even better simply to test the return value of y like this:

   y = self.pilot.controlJoint(None, 'modelRoot', x.getName())
   if y != None:
     y.setHpr(0,0,0)

Since not all the parts returned by by getParts() function will be legitimate joints. The parts that are not joints will return None from controlJoint(), which is a more reliable test than trying to exclude certain parts by name.

David

Ahhh I see… thanks for all the help.

Ok I am running into a new problem but I have NO clue what it means so here is the error message
StandardError: controlled joint is not present

My latests code.


self.joints = []
  self.trye = self.getParts(self.pilot.getPart('modelRoot').node().getBundle())
  
  for x in self.trye:
   y = self.pilot.controlJoint(None, 'modelRoot', x.getName())
   if y != None:
    self.joints.append(y)
    print y.getName()

Ah, OK. My bad. It’s not completely true you can pass any part to controlJoint(). It turns out controlJoint() will let you pass certain parts that aren’t really joints, but then gets mad when you later try to play an animation, and the animation channels don’t have any data for that “joint”.

Try this modification:

  for x in self.trye:
   if isinstance(x, CharacterJoint):
    y = self.pilot.controlJoint(None, 'modelRoot', x.getName())
    self.joints.append(y)
    print y.getName() 

The above code is improved, because it checks the type of each part before passing it to controlJoint(), which ensures that it only passes legitimate CharacterJoint parts to controlJoint.

David

Awesome the project finally works thanks for all the help.