Re: [Maya-Python] Use a variable with setAttr ?

841 views
Skip to first unread message

Kurian O.S

unread,
Aug 10, 2012, 12:22:18 PM8/10/12
to python_in...@googlegroups.com
try this

def L_arm_FK(self,ctrlselected ,*args ):
    #so I want something like : boby:L_Arm_CtrlShape.FKIK_Blend
    for each_ctrl in ctrlselected:
        setAttr = cmds.setAttr('%s.FKIK_Blend' % each_ctrl, 0, edit=True)



On Fri, Aug 10, 2012 at 4:50 AM, Florian Croquet <fcro...@gmail.com> wrote:
def L_arm_FK(self,ctrlselected ,*args ):
      
      
      #so I want something like : boby:L_Arm_CtrlShape.FKIK_Blend
      setAttr = cmds.setAttr(ctrlselected + '.FKIK_Blend', 0, edit=True)



--
--:: Kurian ::--

Florian Croquet

unread,
Aug 10, 2012, 1:52:49 PM8/10/12
to python_in...@googlegroups.com
Thank you Kurian,

Unfortunately, I forgot my file at work so I will try monday, I hope it will work

PS: dear admin, sorry for my triple post but I had an issue with chrome :/

Kurian O.S

unread,
Aug 10, 2012, 2:01:36 PM8/10/12
to python_in...@googlegroups.com
most probably ctrlselected is list  so thats why you getting that error. if you using cmds.ls(sl=True) to get ctrlselected then ls will always return a list ie :

import maya.cmds as cmds
cmds.ls(sl=True)
# Result: [u'pSphere1'] # 

so a for loop will help you in this case :)




--
--:: Kurian ::--

Florian Croquet

unread,
Aug 10, 2012, 7:55:54 PM8/10/12
to python_in...@googlegroups.com
Yes I guessed that the list was the source of the problem but I didn't know how to get the data out of that list ^^

Florian Croquet

unread,
Aug 10, 2012, 8:01:05 PM8/10/12
to python_in...@googlegroups.com
Moreover, I totaly forgot the trick with %s in a string -_-"

Florian Croquet

unread,
Aug 13, 2012, 4:45:43 AM8/13/12
to python_in...@googlegroups.com
I works ! Thank you again 

Florian Croquet

unread,
Aug 14, 2012, 4:50:06 AM8/14/12
to python_in...@googlegroups.com
I have another little question,

Is it possible to open this export window with python or mel ? 


Justin Israel

unread,
Aug 14, 2012, 2:24:18 PM8/14/12
to python_in...@googlegroups.com
Here is a little tip. If you turn on History -> Echo All Commands in the script editor, and perform some operations, you will see it spit out the MEL it is executing. When you do that and open Export Selected, you will see it runs a built in command:  ExportSelection
This command is available to both the MEL and python side:

MEL:   ExportSelection;
PY:     cmds.ExportSelection()



Florian Croquet

unread,
Aug 15, 2012, 9:45:56 AM8/15/12
to python_in...@googlegroups.com
Thank you Justin, it's a very handy trick !

Florian Croquet

unread,
Aug 16, 2012, 6:40:40 AM8/16/12
to python_in...@googlegroups.com
I have another question, in a script I used the command :  cmds.warning("string" ).
It's very useful and I'm now looking for something similar but with another color.

Do someone know if there is another command which allow to display a message in the command window ( in green if possible )
I tried to find something on the python documentation, but I couldn't find anything

I have another thing in mind for a futur script, I would like to take a pictures of a model inside maya, a simple print screen but I want print only 250*300 pxl  of my screen.
Do you think that it's possible in Python ? 

Justin Israel

unread,
Aug 16, 2012, 3:14:37 PM8/16/12
to python_in...@googlegroups.com
Do you mean the commandLine widget, that has the input on the left and the output on the right, at the bottom of the main window?
While it does have a background color attribute, it doesn't perform the same result as when a warning or error is generated (yellow/red).
It just outlines it.

For the screen cap, there are a couple solutions you could use. 

A super duper basic way would be to do a viewport playblast to an image, and then perform whatever cropping you want on the resulting image file:

cmds.playblast( frame=cmds.currentTime(q=True),
                f="viewport.png", 
                fo=True, fmt="image", viewer=False,
                c="PNG", quality=70, rfn=True )

Another way would be to use the API to get an MImage of the current viewport. Nathan Horne has an example of doing this and writing to a file: http://nathanhorne.com/?p=261

import maya.OpenMaya as om
import maya.OpenMayaUI as mui

image = om.MImage()
view = mui.M3dView.active3dView()
view.readColorBuffer(image, True)
image.writeToFile("viewport.png", "png")

But again, you will need to perform the cropping using your own lib.

And lastly, if you want to perform the entire process before writing to a file, and you already happen to have PyQt4 installed for Maya, you can transfer the pixel buffer over to a QImage:

import maya.OpenMaya as om
import maya.OpenMayaUI as mui
import sip

from PyQt4 import QtCore, QtGui

image = om.MImage()
view = mui.M3dView.active3dView()
view.readColorBuffer(image, True)

w,h = view.portWidth(), view.portHeight()

vptr = sip.voidptr(long(image.pixels()))
i = QtGui.QImage(vptr, w, h, QtGui.QImage.Format_RGB32)
trans = QtGui.QTransform()
trans.scale(-1, 1)
trans.rotate(180)
i = i.transformed(trans, QtCore.Qt.SmoothTransformation).rgbSwapped().copy(0,0,300,200)
i.save("screencap.png")



What this does is gets the pixel array from the MImage, then creates a QImage from that data directly. The data was in a bit of a different format, so I had to flip it on X and then rotate it. Also, I needed to swap the rgb channels into the right order. You can perform the crop you want using that copy method. It takes the x,y points and the width height.
Message has been deleted

Florian Croquet

unread,
Aug 16, 2012, 5:25:28 PM8/16/12
to python_in...@googlegroups.com
Thank you again Justin !

I had this impression that one day when I was using a tool of Maya I got a green commandLine (yes, the one which display the warning cmds), but may be I dreamed about it.
The fact is that I'm a bit lazy ,I like the Ui I just created. But I forgot to place a feedback field, that's why I wanted to use this commandLine .... if it's not possible, I will simply rework my UI  ^^

About the picture, it seems to be easy to take one, I didn't thought about using Playblast because I thought it was only for creating short quicktime files.
However, I didn't really got it with Qt. In fact I started python 13 days ago and I didn't dig into Qt.
Maybe it will be more easy to grab a picture of  the viewport and resize the picture to fit my images' size.

Regards

Florian

Florian Croquet

unread,
Aug 17, 2012, 4:31:57 AM8/17/12
to python_in...@googlegroups.com
I tried the cmds.playblast and it worked , but the quality of the picture is very bad ( the picture's size is  250*300 and the resolution of my screen is 2560*1440) 
I found the flag percent won the python documentation, but even à 100 the quality is bad, I tried to put it at 200, the quality is good but it double the size of my picture even if I set up a width and a height :/

Florian Croquet

unread,
Aug 17, 2012, 7:21:46 AM8/17/12
to python_in...@googlegroups.com
Forget what I said, in fact the resulte is good inside maya but the picture's preview in the finder was bad.
My problem is solved 

Florian Croquet

unread,
Aug 20, 2012, 5:08:17 AM8/20/12
to python_in...@googlegroups.com
Hello, today another problem ^^

I encounter a problem with a "else:" and a cmds.textField

I just write this simple code :

pathForText = projectPathPreview + "Comments/" +selectedCharacterPreview + ".txt"

if os.path.exists(pathForText):
        self.commentPreview(pathForText)
else:
      print "NOPE"
      cmds.textField(self.widgets["Info"],edit =True,text= "No comments")

commentPreview execute a command :
            cmds.textField(self.widgets["Info"],edit =True,text= "Comments bla bla bla")

the if statement is working correctly and my function display the right message in my textField
Print "Nope" is also working

But cmds.textField(self.widgets["Info"],edit =True,text= "No comments") return me an error "# Error: KeyError: file /code.py line 550: Info

Is it possible that the cmds,textFields can not be performed inside an else statement ? 


Sveinbjörn J. Tryggvason

unread,
Aug 20, 2012, 5:30:58 AM8/20/12
to python_in...@googlegroups.com
No, it's telling you that the key "Info" does not exist in the self.widgets dictionary. cmds.textField calls, like any function call, is valid within an else clause

Hope this points you in the right direction.

-Svenni

Florian Croquet

unread,
Aug 20, 2012, 5:40:22 AM8/20/12
to python_in...@googlegroups.com
Thank you for the answer,

My "Info" does exist, because the same command in the if statement is working :/ 

Florian Croquet

unread,
Aug 20, 2012, 6:46:44 AM8/20/12
to python_in...@googlegroups.com
As usual, I find something else :D
However if someone has an Idea I will be glad to hear it

Florian Croquet

unread,
Aug 22, 2012, 8:15:45 AM8/22/12
to python_in...@googlegroups.com
Hi,

I have a question about the command : cmds.ls
Have a script which allow me to duplicate a object and rename it, the name of the object follow this model : Gizmo_NameA, Gizmo_NameB,Gizmo_NameC ...
I have a lot's of other object in my scene but I want to list all my Gizmo items in the scene.

So I started with cmds.ls and I thought that I could find a Flag that allow me to filter my list with the a part of the name : "Gizmo_".
But when I looked on the documentation, I didn't find anything. 
I tried to find something on google and I found this post http://forums.cgsociety.org/archive/index.php/t-998695.html which seems to be interesting but a part of the code has been replaced by another thing 
I found cmds.filter but it doesn't seem to filter a list by name 

Somebody has an idea ?

Best, 

Florian

stephenkmann

unread,
Aug 22, 2012, 9:18:32 AM8/22/12
to python_in...@googlegroups.com
The Mel command ls has a flag -ap   For all paths 

ls  -ap "Gizmo_*" 

Should give you what your looking for 

--


--
stephe...@gmail.com
http://smannimation.blogspot.com/
http://nymayausersgroup.blogspot.com/
http://smann3d.blogspot.com/

Florian Croquet

unread,
Aug 22, 2012, 10:02:05 AM8/22/12
to python_in...@googlegroups.com
Thank you smann,

The command work in mel. But I don't know how to properly translate that in python :/
I tried : 

import maya.mel as mel
lookingForGizmo = mel.eval("ls -g -ap 'Gizmo_*' ; ")

Obviously I have a Syntax error

damon shelton

unread,
Aug 22, 2012, 10:05:11 AM8/22/12
to python_in...@googlegroups.com
import maya.cmds as cmds
lookingForGizmo = cmds.ls('Gizmo_*', g = True, ap = True)

--

Florian Croquet

unread,
Aug 22, 2012, 10:10:56 AM8/22/12
to python_in...@googlegroups.com
Yeah obviously I m so stupid -_-" 

Thank you damonshelton 

Florian Croquet

unread,
Aug 23, 2012, 5:06:36 AM8/23/12
to python_in...@googlegroups.com
Hi,

I keep working on this code, I want to create a sort of auto rig tool. I'm not sure that I'm doing it right but anyway I will learn with my mistakes :D 

So if you remembered, I get in my list all my gizmo item and I want to use them in order to replace my bones.
So I created this "for xxx in xxxx"

    def moveSkeletonProcess(self,*args):
        lookingForGizmo = cmds.ls('Gizmo_*', g = True, ap = True)
    
        print lookingForGizmo
        
        for gizmo in lookingForGizmo:
            #self.moveBonesToGizmo(gizmo)
            
            gizmoName = gizmo.rpartition("Shape")[0]
    
            boneName = gizmoName.rpartition("Gizmo_")[2]
            
            
            wst = cmds.xform(gizmoName,q =True ,ws = True ,t = True) 
            move = cmds.xform(boneName, ws = True , t = wst) 

You can see the result here : http://www.youtube.com/watch?v=L4Js8ajGZFM 

It works but I need to press the button 4 times if I want everything in place :(. I don't understand why my boucle doesn't work , could it be a problem with my bones' rotation axis ?          

Nicolas Combecave

unread,
Aug 23, 2012, 7:59:03 AM8/23/12
to python_in...@googlegroups.com
You need to make sure you process your list in the same way the hierarchie is made.
If you move a child into the right place, and then the parent, the child will get an offset.


2012/8/23 Florian Croquet <fcro...@gmail.com>

--

Florian Croquet

unread,
Aug 23, 2012, 8:04:58 AM8/23/12
to python_in...@googlegroups.com
Ok so that means that I have to write by hand my list and  I can't use :         lookingForGizmo = cmds.ls('Gizmo_*', g = True, ap = True)

Nicolas Combecave

unread,
Aug 23, 2012, 8:33:06 AM8/23/12
to python_in...@googlegroups.com
I think that if you use 

lookingForGizmo  = cmds.ls('Gizmo_*', dag = True, l = True, ap = True, g = True)

lookingForGizmo.reverse()


You should have a list in hte same order as the hierarchy.
Also try to use long names to avoid problems of duplicate nodes when you work with hierarchies. Maybe you'll have to deal with long names if you are processing htose strings to rename objects, but it's well worth the (little) effort in order to always have consistent/predictable results.

Nicolas


2012/8/23 Florian Croquet <fcro...@gmail.com>
Ok so that means that I have to write by hand my list and  I can't use :         lookingForGizmo = cmds.ls('Gizmo_*', g = True, ap = True)

--
Message has been deleted

Florian Croquet

unread,
Aug 23, 2012, 8:52:19 AM8/23/12
to python_in...@googlegroups.com
Yes but it doesn't seem to work, cmds.ls list my object by alphabetical order.
 
I tried with your flags but they have also another order and it doesn't provide me my outliner order.

the first line is with your cmds.ls and the second is my hand typed list 

I guess you're right, I should create a hierarchy for my gizmo but finally it works with this other solution so .... 

Justin Israel

unread,
Aug 23, 2012, 11:56:53 AM8/23/12
to python_in...@googlegroups.com, python_in...@googlegroups.com
Without having tested it yet, I believe when you use the wild card, maybe it is causing a sort. Possibly what you will need to do is to just first get the Gizmo nodes you want, long path, without any parents or children. Then loop over each one and use listRelatives to produce the hierarchy you want for each node. But you will still need to use that same advice to process the hierarchy in reverse 
--

Nicolas Combecave

unread,
Aug 24, 2012, 8:54:47 AM8/24/12
to python_in...@googlegroups.com
I've tested this and it seems to work as you need:

import maya.cmds as cmds
import random

# CREATING RANDOM LOCATORS AND JOINTS TO TEST SNAPPING HIERARCHIES
max = 10
prevLoc = None
prevJoint = None

for i in range(max):

    loc = cmds.spaceLocator(name = "Gizmo_"+str(i))
    cmds.xform(worldSpace = True, t = [random.random()*10, random.random()*10, random.random()*10])
    cmds.select(cl = True)
    joint = cmds.joint(name = "joint_"+str(i), position = [random.random()*10, random.random()*10, random.random()*10])
    
    if prevLoc != None:
        cmds.parent (loc[0], prevLoc[0])
    if prevJoint != None:
        cmds.parent (joint, prevJoint)

    prevLoc = loc
    prevJoint = joint

# HERE YOU CAN REPARENT SOME LOCATORS AND JOINTS IN THE SAME WAY IN ORDER TO TEST HIERARCHIES WITH BRANCHES

# NOW SNAPPING JOINTS HIEARCHY TO LOCATORS HIERARCHY
# WE ASSUME YOU DON'T HAVE DUPLICATE SHORT NAMES IN JOINTS HIERARCHY
liste = cmds.ls('Gizmo_*', type = "transform", dag = True, l = True)

for gizmo in liste:
    gizmo_id = gizmo.split('|')[-1].split('_')[-1]
    joint_id = "joint_" + gizmo_id
    gizmoPos = cmds.xform(gizmo, q = True, worldSpace = True, t = True)
    cmds.xform(joint_id, worldSpace= True, absolute = True, t = (gizmoPos[0],gizmoPos[1],gizmoPos[2]))
    
    
    
Anyway, it's always a good thing to have a little utility function to order list by hierarchy 
Here is one quickly hacked:

def sortByHierarchy(dagList):
    # we'll use '@' as it can't never be found in maya node names
    
    sortedByHierarchy = []
    
    for elem in dagList:
        depth = elem.count('|')
        sortedByHierarchy.append (str(depth) + "@" + elem) 
    for i in range(sortedByHierarchy.__len__()):
        sortedByHierarchy[i] = sortedByHierarchy[i].split('@')[1]
    
    return sortedByHierarchy
     
print sortByHierarchy(liste)

Nicolas

Justin Israel

unread,
Aug 24, 2012, 12:12:35 PM8/24/12
to python_in...@googlegroups.com
Maybe I am missing something, but it doesn't seem like the sortByHierarchy() function is doing anything.
It takes in a list, then loops over it, creating a new list with the depth count + @ + name. Then it just loops back over the new list, and replaces it with the name again. But no sorting is happening at all.

If that function is supposed to simply sort by the depth value, couldn't you just do this?

    dagList.sort(key=lambda x: x.count('|'))
    # dagList.sort(key=lambda x: x.count('|'), reverse=True)

What is the logic of concatenating the depth + @ + name?


--

Nicolas Combecave

unread,
Aug 24, 2012, 1:10:19 PM8/24/12
to python_in...@googlegroups.com
Damn, your version is QUITE shorter!

As my python is very weak, I tried to do a conversion of how I'd do it in mel!
I sure do need to deepen my python seriously...
Although I don't fully understand the lambda usage, I sure will look into it right now ^^
 
So, about the (lame and lenghty) function I sent before, that was doing nothing, it's because in the process of cleaning for pasting into gmail, I forgot the sort command... 

It should have been like this...

def sortByHierarchy(dagList):
    # we'll use '@' as it can't never be found in maya node names
    
    sortedByHierarchy = []
    
    for elem in dagList:
        depth = elem.count('|')
        sortedByHierarchy.append (str(depth) + "@" + elem) 

    sortedByHierarchy.sort()

    for i in range(sortedByHierarchy.__len__()):
        sortedByHierarchy[i] = sortedByHierarchy[i].split('@')[1]
    
    return sortedByHierarchy


The idea was to prefix each long name with it's depth info, sort that, and strip back this depth info to return a proper list...

Nicolas



2012/8/24 Justin Israel <justin...@gmail.com>

Nicolas Combecave

unread,
Aug 24, 2012, 1:21:13 PM8/24/12
to python_in...@googlegroups.com
Actually, looking at the python doc for the list.sort() method, it doesn't mention optional arguments...

I've had to search in here to find the info:


2012/8/24 Nicolas Combecave <zezebub...@gmail.com>

Justin Israel

unread,
Aug 24, 2012, 1:27:06 PM8/24/12
to python_in...@googlegroups.com
Well ya, but in your code it wasn't sorting at all. What was it trying
to do actually?

From a python interp you can do:
>>> help([].sort)
sort(...)
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1



On Fri, Aug 24, 2012 at 10:21 AM, Nicolas Combecave

Nicolas Combecave

unread,
Aug 24, 2012, 1:33:30 PM8/24/12
to python_in...@googlegroups.com
It does the same as yours but it's okay to say it's lame, obfuscated and not leveraging python power ^^


2012/8/24 Justin Israel <justin...@gmail.com>

Justin Israel

unread,
Aug 24, 2012, 1:37:39 PM8/24/12
to python_in...@googlegroups.com
Haha, no don't get me wrong. I am totally NOT making a statement that
it is lame. I was saying that I don't see where the sort aspect is
occurring in your function. All i see is that you append them to the
list and then go back over that same list and strip away the bit you
put in front again. How does it sort?


On Fri, Aug 24, 2012 at 10:33 AM, Nicolas Combecave

Justin Israel

unread,
Aug 24, 2012, 1:40:50 PM8/24/12
to python_in...@googlegroups.com
Example:

dagList = ['|a|b|c', '|a', '|a|b', '|a']

print sortByHierarchy(dagList)
# ['|a|b|c', '|a', '|a|b', '|a']

Nicolas Combecave

unread,
Aug 24, 2012, 8:36:39 PM8/24/12
to python_in...@googlegroups.com
Yeah,
My first post missed an essential statement, which unfortunaetly, was the core aspect of the function, the sort part of the outputed list.
I replied with the corrected version (I set it in bold but I don't know if everyone sees it in bold), and it then works as expected

def sortByHierarchy(dagList):
    # we'll use '@' as it can't never be found in maya node names
   
    sortedByHierarchy = []
   
    for elem in dagList:
        depth = elem.count('|')
        sortedByHierarchy.append (str(depth) + "@" + elem)

    # this was the essential part of the function
    sortedByHierarchy.sort()   

   for i in range(sortedByHierarchy.__len__()):
        sortedByHierarchy[i] = sortedByHierarchy[i].split('@')[1]
   
    return sortedByHierarchy

dagList = ['|a|b|c', '|a', '|a|b', '|a']

print sortByHierarchy(dagList)

# ['|a', '|a', '|a|b', '|a|b|c']

Anyway, it's useless to say that your version is MUCH more sexy, and after reading python doc, MUCH more efficient on big lists.

Justin Israel

unread,
Aug 25, 2012, 11:23:06 AM8/25/12
to python_in...@googlegroups.com, python_in...@googlegroups.com
Ah, got it! Just a missing line. Makes sense. I think thats called a Shwartzian Transform? 
http://en.m.wikipedia.org/wiki/Schwartzian_transform , where you map the data to something with key priority, then sort, then map it back. 
Interestingly, I believe that is what the key argument of the sort function does under the hood, in the C side. 
But the sort function could also be used on a list of tuples. Another manual way to do your version would be to do:
1)  [ (depth, path), (depth, path) ]
2)  sort()
3)  [ item[1], item[1] ]

All of this depends on how expensive each option would be. 

Nicolas Combecave

unread,
Aug 25, 2012, 12:17:29 PM8/25/12
to python_in...@googlegroups.com
Man I must say I'm impressed as much by your deep knowledge, and your dedication to this list...
I'm the kind of lurker-type, and your amount of valuable input is quite bold!
Anyway, I didn't know about the Schwartzian_transform, and yes it's exactly that:

map
sort
unmap

I didn't come to this by myself, as I saw it a long time ago in another renaming mel script, and I did find it quite clever.

Nicolas


2012/8/25 Justin Israel <justin...@gmail.com>

Justin Israel

unread,
Aug 25, 2012, 1:09:07 PM8/25/12
to python_in...@googlegroups.com, python_in...@googlegroups.com
Well thanks. I just enjoy the conversations really :-)
You are right that in MEL you would have to take a different approach than what is available to you in Python. 


Florian Croquet

unread,
Aug 27, 2012, 7:07:53 AM8/27/12
to python_in...@googlegroups.com
Thank you for those pieces of advices ^^


Matt Estela

unread,
Aug 27, 2012, 9:06:53 AM8/27/12
to python_in...@googlegroups.com
Yep, you go above and beyond Justin, much obliged!


On Mon, Aug 27, 2012 at 9:07 PM, Florian Croquet <fcro...@gmail.com> wrote:
Thank you for those pieces of advices ^^

Florian Croquet

unread,
Aug 30, 2012, 8:23:47 AM8/30/12
to python_in...@googlegroups.com, matt....@gmail.com
Hi folks,

My tool is almost finish !
Now I need to copy my weight information from a model to another model (in fact it's the same model with a blendshape)
I tried the function Skin>Edit Smoth Skin>Import Skin Weight Maps (obviously with its sister Export Skin Weight Maps), and it works perfectly 

So I wanted to translate this into python. But this function doesn't seem to have a Python equivalent, in fact I guess it's a mel script (I tried to turn on the all echo command but I didn't understand anything :D ) 
Does somebody have idea for this or another solution ? 
Reply all
Reply to author
Forward
0 new messages