setAttr function in Autodesk Maya - python

I am still learning Python in Maya. I cannot get my code to work. I am trying to create a locator and parent it under my selection and then zero out the locators transforms.
import maya.cmds as cmds
sel = cmds.ls(selection = True)
loc = cmds.spaceLocator()
cmds.parent(loc, sel)
cmds.setAttr(loc, "translateX", 0)
I always get this error message:
#Error: TypeError: file <maya console> line 7: Invalid argument 1, '[u'locator6']'. Expected arguments of type ( list, )
Sometimes with a bit other code I get something like:
#There does not exist something with name 'translateX'
I know that it does work when I replace loc with the name of the locator, but I try to keep the code as universal as I can and not bound to the name of a locator.
How does the setAttr function work in Maya with variables? Maya docs and other questions at various forums could not help... :/

setAttr takes one complete attribute as its argument:
cmds.setAtt( loc + ".translateX", 0)
where loc has to be a single string. spaceLocator like most creation commands returns a list, not a single string. So the whole thing is:
sel = cmds.ls(selection = True)
loc = cmds.spaceLocator()
cmds.parent(loc, sel)
cmds.setAttr(loc[0] + ".translateX", 0)

I know you seem to be asking asking for maya cmds but I'd like to chime this in as an alternative.
In PyMel the spaceLocator function returns the created object itself. The attributes are then methods inside the object, allowing you to do the following. One reason why I love PyMel!
import pymel.core as pm
sel = pm.selected()[0]
loc = pm.spaceLocator()
pm.parent(loc, sel)
loc.translateX.set(0)

Related

'int' object has no attribute 'set'

I'm working on a project where you click a button and it changes an int and writes it to the screen. My issues is that when I try to set a new value to the int it comes back with an AttributeError.
def busy():
unit_status.set(7)
Everything else is working except for that one line, and I can't for the life of me figure out why.
While this thread is a bit old, I dont think LouieC's response fully answered the OP's concern.
LouieC mentions that set is a built-in class, which is correct. But it is likely Warrior's Path was looking for the values, since he wanted to write them to the screen.
IF he didnt ask, then I am asking based upon an observation in the following code, adapted from the geeksforgeeks.org explanation. My point is addressed in the comments, particularly at the end.
Notice when LouieC's technique is applied it seems to incorrectly overwrite the entirety of IntVar.
# importing tkinter module
from tkinter import *
# creating Tk() variable
# required by Tkinter classes
master = Tk()
# Tkinter variables
# initialization using constructor
intvar = IntVar(master, value = 25, name ="2")
strvar = StringVar(master, "Hello !")
boolvar = BooleanVar(master, True)
doublevar = DoubleVar(master, 10.25)
print(intvar) # This prints the NAME, not the value.... the name is auto-assigned by python
print(strvar) # if not explicity declared...
print(boolvar)
print(doublevar)
print(intvar.get()) # This prints the VALUE, not the name....
print(strvar.get())
print(boolvar.get())
print(doublevar.get())
# But now watch what happens...
intvar = 1
print(intvar)
print(intvar.get())
# What's interesting here is... print(intvar.get()) worked at line 20...
and yet now it generates the following error
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-61984dfda0fb> in <module>
26 intvar = 1
27 print(intvar)
---> 28 print(intvar.get())
AttributeError: 'int' object has no attribute 'get'
If one runs a type test, in the first case, around line 20:
print(type(intvar))
One will get:
<class 'tkinter.IntVar'>
But if one runs the same type test after LouieC's reassignment, one will get:
<class 'int'>
That's why I said the reassignment doesnt work right.
The OP's question still seems to be open.
This is not how you reassign a variable of type integer; you want:
unit_status = 7
set is a built-in class in Python; official docs here
A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. (For other containers see the built-in dict, list, and tuple classes, and the collections module.)

How to get node parameter in Houdini with Python

I am very much new to Houdini and this might be something very obvious to ask but I have hit a brick wall. I would like to store a parameter, specifically the File Name of an alembic object so that I can validate the filename to see if it follows a namespace convention
The following is all I have
import hou
node = hou.node('obj/alembic1/alembic1')
after getting the node, how would I get the File Name property? Any guidance is greatly appreciated
There's two main ways:
1 As you you've started to do in your code, access the node then access the parm HOM method of Node:
parm = hou.node('obj/alembic1/alembic1').parm('fileName')
2 Use hou.parm directly:
parm = hou.parm('obj/alembic1/alembic1/fileName')
parm is an object representing a parameter, to get the value of the parameter you need to call it's eval method:
parmval = parm.eval()
So something like this is the usual case:
node = hou.node('obj/alembic1/alembic1')
parmVal = node.parm('fileName').eval()
Note that parm.eval() will work for most cases, but sometimes you might need more verbose methods such as parm.evalAsNode(). Check out the help here.
You can see the parm name to use in your code when you hover over the parameter name you want to access in the parameters window. Ie if you hover over "File Name" in the Alembic node it will show:
Parameter: fileName

addAttr method on pymel objects

I can't seem to utilize the addAttr method correctly. I'm using the same arguments as when I call from pymel.core but it's not giving me the same results.
I'm trying to add a custom message attribute so I can easily search for certain types of objects later. When I do it from pymel.core and include the same object reference as an argument, it works fine.
#get object reference
test_object = pm.ls(sl=1)[0]
#this one spits out an error
test_object.addAttr(longName = 'custom', attributeType = 'message')
#this one works fine
pm.addAttr(test_object, longName = 'custom', attributeType = 'message')
I keep getting this error
Error: TypeError: file line 1: addAttr() takes exactly 2 arguments (1 given)
What additional argument is it looking for when I use it this way? I am clearly missing something obvious about how methods work but I can't figure it out.
The addAttr method exposed for DG nodes in Maya PyMel has following signature.
addAttr(attr, **kwargs)
Here attr is an positional argument representing the attribute name. The kwargs can be supplied with all other relevant flags used in pm.addAttr() method. So you have to pass the attribute name as first argument.
node.addAttr('custom', attributeType='message')
Hope this will help.
from cgsociety thread
pCube.addAttr('timeBasedAttr', keyable=True, attributeType='float', min=0.0, max=1.0)
you should write :
test_object.addAttr('custom', attributeType = 'message')
Ive tried and it doesn't output error.

ValueError: No object matches name: in Maya Python

I have a code that returns an error of
ValueError: No object matches name: s
I'm not sure why it is looking for the object s.
The code is as follows
import maya.cmds as cmds
def createOffsetGrp(objSel):
for obj in objSel:
p = cmds.listRelatives(obj,parent=True)
print (p)
createOffsetGrp('spine02_jnt')
By expectation, the print command should spit out Spine01_jnt which is the parent of the Spine02_jnt
Is there something I missed?
Thanks to duck typing in Python, sometimes such errors can be hard to catch. What is happening here is your function is expecting an array as argument, but you are passing a string.
Python supports iterating over a string as well, by listing out individual characters, which is why it is looking for the s in spine02_jnt. Passing your string within an array should solve your problem:
createOffsetGrp(['spine02_jnt'])
in addition of what crazyGamer, you can provide some support on string like this :
import maya.cmds as cmds
def createOffsetGrp(objSel):
# isinstance is used to check the type of the variable :
# i.e: isinstance(objSel, int)
# basestring is a type combining unicode and string types
if isinstance(objSel, basestring):
objSel = [objSel]
for obj in objSel:
p = cmds.listRelatives(obj,parent=True)
print (p)
createOffsetGrp('spine02_jnt')

Get number of args for function

I have a module, ui. I'd like to get a list of all the classes that ui defines which are a subclass of ui.View, and that can be called without arguments.
I've tried the following code:
ui_elements=[d for d in ui.__dict__.values() if type(d)==type and inspect.getargspec(d.__init__)[0]==1 and isinstance(d(),ui.View)]
But I get the following error from inside the inspect module:
TypeError: <slot wrapper '__init__' of 'object' objects> is not a Python function
I'm using inspect instead of a try: except: just because checking beforehand seems like a better solution than trying it to see if it works.
So, how can I get a list of all the classes that subclass ui.View and do not require arguments to create? I'd like to do this inline if possible, and I'd also like to avoid using try:/except: statements.
To get a list comprehension with try/except you can use a local function:
def tryCreate(class_):
try:
return class_()
except:
return None
ui_elements = set(tryCreate(d) for d in ui.__dict__.values()
if issubclass(d, ui.View)) - set(None)
Okay, it's a set comprehension in the end ;-)
As said in comments, you should use try/catch, but if you really want to do it that way...
First, use inspect to check if your symbol is a class, use issubclass as suggested in comments and you want the number of arguments to be 1, not the first argument to be 1. So, something like this:
ui_elements = [ d for d in ui.__dict__.values()
if (inspect.isclass(d) and
issubclass(d, ui.View) and
inspect.ismethod(d.__init__) and
len(inspect.getargspec(d.__init__)[0]) == 1) ]

Categories