Pymel variable to expression

505 views
Skip to first unread message

James

unread,
Apr 7, 2011, 11:52:07 PM4/7/11
to Pymel Python Module for Maya
Hi guys,

I haven't coded within Maya in years, but I'm trying to pick it back
up again with Pymel. I'm on day 2 now and ran into a hurdle this
afternoon. I think it's my lack of understanding of how it works
together..

Basically, I'm setting an expression through Pymel. I'm trying to use
a variable in my expression.


Logically I want to try this:

radius=9
pm.expression( o='fronttire', s='fronttire.translateX = radius *
sin(fronttire.translateX)' )


But since it doesn't work, I tried this:

radius=9
pm.expression( o='fronttire', s= 'fronttire.translateX =
sin(fronttire.translateX)' * radius )


At the end of the day, it would have to be written in MEL for the
expression to understand it. So I'm guessing maybe the variable has to
be converted first?

Any help and I'll be your best friend... :P

Ofer

unread,
Apr 9, 2011, 3:52:52 AM4/9/11
to Pymel Python Module for Maya
You could inject the radius into the expression using string-
formatting:

pm.expression( o='fronttire', s= 'fronttire.translateX =
sin(fronttire.translateX) * %s' % radius )

but I would recommend simply using an extra attribute on the maya node
to hold the radius value:

tire = pm.PyNode('fronttire')
tire.setAttr('radius', 9, force=1) # create and set the attribute
at once
pm.expression(o = tire, s = '%(tire)s.translateX = sin(%
(tire)s.translateX) * %(tire)s.radius' % {'tire': tire} )

Leonid Onokhov

unread,
Apr 8, 2011, 2:03:27 AM4/8/11
to py...@googlegroups.com
pm.expression is just a wrapper for maya `expression` command.

Here is maya doc:

This command describes an expression that belongs to the current scene. The expression is a block of code of unlimited length with a C-like syntax that can perform conversions, mathematical operations, and logical decision making on any numeric attribute(s) in the scene. One expression can read and alter any number of numeric attributes. Theoretically, every expression in a scene can be combined into one long expression, but it is recommended that they are separated for ease of use and editing, as well as efficiency.

So, that -s flag passes 'string' expression which is not python and somewhat not mel.

You need to make whole valid expression string and pass it to command.
Like that (if radius is float)

>>>radius = 9 # this one is python interpreter variable, it has nothing to do with expression
>>> myexpr = 'fronttire.translateX=sin(fronttire.translateX)* %f' % radius
>>> print myexpr
fronttire.translateX=sin(fronttire.translateX)* 9.0000;
>>>pm.expression(o='fronttire', s=myexpr)

String formatting operator '%' will replace %f token in string with radius value. Python printf-like string formatting is described here http://docs.python.org/release/2.6.6/library/stdtypes.html#string-formatting.
String myexpr containing expression is passed to pm.expression command which will then create expression node - just like maya expression command.
After that changing radius variable will not affect your expression.

Now, if you want to be able to dynamically change radius, you should add attribute controling the radius to any node you like, and make expression like 'fronttire.translateX=sin(fronttire.translateX)* myControlNode.tireRadius'.

Using python and pymel is same as using mel, but with proper language instead of ugly shell scripting.
I recommend you reading python tutorial http://docs.python.org/release/2.6.6/tutorial/index.html, it really helps.


--
You received this message because you are subscribed to the Google Groups "Pymel Python Module for Maya" group.
To post to this group, send email to py...@googlegroups.com.
To unsubscribe from this group, send email to pymel+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pymel?hl=en.


James

unread,
Apr 10, 2011, 7:06:00 PM4/10/11
to Pymel Python Module for Maya
Hi guys,

Thanks for your responses, they both really helped. I actually went
out and got a Python book after reading your replies. I definitely
understand a little more of how the string formatting is working. But
this problem was so basic, I feel like I have a mountain to climb :P

I wasn't planing on setting an attribute straight to the node, I was
going to hold it in the script until the expression is written.

def findRadius():
#get wheel name
wheelname=pm.ls( selection=True )
#rename wheel to something logical
pm.rename(wheelname,"fronttire")
#get radius through BB information
bbox = pm.exactWorldBoundingBox("fronttire")
oradius=bbox[4]/2
return oradius

radius=findRadius()

pm.expression( o='fronttire', s= 'fronttire.translateX =
sin(fronttire.translateX) * %s' % radius )


Do you think it would be better to add the attribute to the node?
This script is a part of a vehicle rigging scripts that I'm throwing
together. Thanks again and I hope to be on these forums long enough to
help others once I graduate to your level. Also, I know the code
snippet is quite small but any critiques or recommendations on how to
make it look better, more pro or efficient, I'm all ears.



On Apr 8, 2:03 am, Leonid Onokhov <sop...@gmail.com> wrote:
> pm.expression is just a wrapper for maya `expression` command.
>
> Here is maya doc:
>
> This command describes an expression that belongs to the current scene. The
> expression is a block of code of unlimited length with a C-like syntax that
> can perform conversions, mathematical operations, and logical decision
> making on any numeric attribute(s) in the scene. One expression can read and
> alter any number of numeric attributes. Theoretically, every expression in a
> scene can be combined into one long expression, but it is recommended that
> they are separated for ease of use and editing, as well as efficiency.
>
> So, that -s flag passes 'string' expression which is not python and somewhat
> not mel.
>
> You need to make whole valid expression string and pass it to command.
> Like that (if radius is float)
>
> >>>radius = 9 # this one is python interpreter variable, it has nothing to
> do with expression
> >>> myexpr = 'fronttire.translateX=sin(fronttire.translateX)* %f' % radius
> >>> print myexpr
>
> fronttire.translateX=sin(fronttire.translateX)* 9.0000;
>
> >>>pm.expression(o='fronttire', s=myexpr)
>
> String formatting operator '%' will replace %f token in string with radius
> value. Python printf-like string formatting is described herehttp://docs.python.org/release/2.6.6/library/stdtypes.html#string-for....
>
> String myexpr containing expression is passed to pm.expression command which
> will then create expression node - just like maya expression command.
> After that changing radius variable will not affect your expression.
>
> Now, if you want to be able to dynamically change radius, you should add
> attribute controling the radius to any node you like, and make expression
> like 'fronttire.translateX=sin(fronttire.translateX)*
> myControlNode.tireRadius'.
>
> Using python and pymel is same as using mel, but with proper language
> instead of ugly shell scripting.
> I recommend you reading python tutorialhttp://docs.python.org/release/2.6.6/tutorial/index.html, it really helps.

Leonid Onokhov

unread,
Apr 11, 2011, 1:59:05 AM4/11/11
to py...@googlegroups.com
If you don't need to change radius after making expression then you don't need attribute.

Ofer

unread,
Apr 11, 2011, 3:45:18 AM4/11/11
to Pymel Python Module for Maya
Adding a radius as an attribute is best practice. It'll be easier to
modify later if needed (instead of editing the expressions, you'll
just change the radius attribute in the channel box; you can even have
it connected to some configuration node that controls all of the tire
radii from one place, etc.), and also more accurate (casting a
floating point number into a string removes precision, much like
1/3~=0.3333).

Also, your 'findRadius' function doesn't just 'finds a radius', it
also changes the name of the selected node to 'fronttire'. I'm
guessing this is only in your example here, but still, functions
should be written so they do a very particular thing and nothing else.
A sign of a well written function is a short function name, and that
it does exactly what its name says. Your function should also accept
as an input argument the node for which to find the radius, and not
rely on current selection. That's bad coding practice, since it relies
on the current system-state to function properly, instead of relying
solely on explicit inputs (the same reason why global variables or a
no-no).

Here's my suggestion:

def findRadius(node):
bbox = pm.exactWorldBoundingBox(node)
return (bbox[4]/2)

radius=findRadius('fronttire')
pm.expression( o='fronttire', s= 'fronttire.translateX =
sin(fronttire.translateX) * %s'  % radius )


Reply all
Reply to author
Forward
0 new messages