Skip to content

Instantly share code, notes, and snippets.

@JFlynnXYZ
Last active August 29, 2015 13:57
Show Gist options
  • Save JFlynnXYZ/9773304 to your computer and use it in GitHub Desktop.
Save JFlynnXYZ/9773304 to your computer and use it in GitHub Desktop.
Centres a selection of objects to the first selected object's rotate pivot.
import maya.cmds as cmds
def _centre_objects(*args):
'''Centres a selection of object's to the first selected objects
rotate pivot.
args : This is a list of objects that can also be used by
the user. If this is blank, then a selection is used instead.
On Exit : Moves all of the objects apart from the first to the
first selected objects scale pivot point.
For example:
>>> import maya.cmds as cmds
>>> box = cmds.polyCube()
>>> cmds.move(10,23,5, box[0], ws=True)
>>> loc = cmds.spaceLocator()
>>> cmds.select((box[0],loc), replace=True)
>>> centre_objects_()
>>> cmds.objectCenter(box[0]) == cmds.objectCenter(loc)
True
>>>
'''
if args != ():
slct = args
else:
slct = cmds.ls(selection=True)
if slct == () or len(slct) < 2:
raise ValueError('You must select at least two '
'different objects')
cmds.move(*cmds.xform(slct[0], q=True, rp=True, ws=True) + slct[1:],ws=True)
_centre_objects()
@JFlynnXYZ
Copy link
Author

Sure:
So, functions can accept un-defined arguments and keywords as parameters. Arguments are values without a name or defining key, where as keywords are values with a key or name to store the value for. In the use of Python functions, arguments are stored in a tuple and keywords in a dictionary.

To use undefined arguments you either use a single asterisk ( * ) followed by a name for the aguments tuple to be stored in or for keywords the use of a double asterisk ( ** ) followed by a name for the keywords dictionary to be stored in. An example function is show below:

>>> def test(par, par2, *args, **kwards):
        print(par)
        print(par2)
        print(args)
        print(kwards)

>>> test('paremeter1','paremeter2', 1,2,3,4,5,6, other=True, over='yes')
paremeter1
paremeter2
(1, 2, 3, 4, 5, 6)
{'over': 'yes', 'other': True}
>>> 

Lets go through this example: the parameters par and par2 are required arguments for the function. The asterisk in front of args means that the variable name will hold a tuple of all non-keyword values not required by the function(Note that this tuple remains empty if no additional arguments are specified during the function call.) The double asterisk in front of kwards means that it will hold all keyword values not required by the function in a dictionary.

Now, for my code I use the asterisk before my variable is so that it turns the list or iterable object and places each of the value as a separate value for the non-keyword argument instead of a list as one item. See the example below:

>>> aList = ('a', 'b', 'c', 'd')
>>> test('par1', 'par2', aList, damn='uhuh')
par1
par2
(('a', 'b', 'c', 'd'),)
{'damn': 'uhuh'}
>>> test('par1', 'par2', *aList, damn='uhuh') #only difference is the use of the asterisk
test('par1', 'par2', *aList, damn='uhuh')
par1
par2
('a', 'b', 'c', 'd')
{'damn': 'uhuh'}
>>>

As you can see, the use of the asterisk unpacks the list and placed them into separate values for the args tuple. Now, to the real question: Why do I use it for my piece of code?

There are a couple of reasons why, the first being this is how Maya functions in Python are setup. Instead of using required parameters, it uses the undefined arguments and keywords. So, if you actually saw the definition for the Python function cmds.move() it would look like this:

def move(*args, **kwards):
    '''do stuff with args and kwards'''
    pass

How the default function for cmds.move works is it expects 4 different arguments when running: it expects x,y,z,[objects] which is essentially the x,y,z coordinates as floats and a list or name of an object to move. This last value isn't necessary and a selection works as well but for my code we need all four. So, what I instead do is craft a tuple with all the values in the form (x,y,z,[objects]) and use an asterisk in front to unpack the values and use in the args variable as separate values.

The other question you may be asking is why do you do this? Well, it's a lot easier then writing out each list position for each value and, most of the time, it's easier to read. It also means you use up less memory and time writing and storing values. It's, for the most part, nicer :)

Hope that helps, best just to experiment with the functions above and see what results you get but you get the hang of it eventually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment