質問

I want to randomly rotate a list of objects on a given axis with a random amount retrieved from a specified range. This is what I came up with:

import pymel.core as pm
import random as rndm

def rndmRotateX(targets, axisType, range=[0,180]):
    for obj in targets:
        rValue=rndm.randint(range[0],range[1])
        xDeg='%sDeg' % (rValue)
        #if axisType=='world':
        #    pm.rotate(rValue,0,0, obj, ws=1)
        #if axisType=='object':
        #    pm.rotate(rValue,0,0, obj, os=1)
        pm.rotate(xDeg,0,0,r=True)

targetList= pm.ls(sl=1)
randRange=[0,75]
rotAxis='world'
rndmRotateX(targetList,rotAxis,randRange)

Im using pm.rotate() because it allows me to specify whether I want the rotations done in world or obj space (unlike setAttr, as far as I can tell). The problem is, it raises this error when I try to run this:

# Error: MayaNodeError: file C:\Program Files\Autodesk\Maya2012\Python\lib\site-packages\pymel\internal\pmcmds.py line 140:  #

It must be something with they way I enter the arguments for pm.rotate() (Im assuming this due to the line error PyMel spits out, which has to do with its arguments conversion function), but I cant figure out for the life of me wth I did wrong. :/

役に立ちましたか?

解決 3

Just as a straight debug of what you've got...

Issue 01: it's case sensitive

pm.rotate("20deg",0,0) will work fine, but pm.rotate("20Deg",0,0) will fail and throw a MayaNodeError because it thinks that you're looking for a node called '20Deg'. Basically, you want to build your string as per: xDeg='%sdeg' % (rValue)

Issue 02: you're relying on pm.rotate()'s implicit "will apply to selected objects" behaviour

You won't see this til you apply the above fix, but if you have two selected objects, and ran the (patched) rndmRotateX function on them, you'd get both objects rotating by the exact same amount, because pm.rotate() is operating on the selection (both objects) rather than a per-object rotation.

If you want a quick fix, you need to insert a pm.select(obj) before the rotate. And you possibly want to save the selection list and restore it...however IMHO, it's a Really Bad Idea to rely on selections like this, and so I'd push you towards Kim's answer.

他のヒント

I think the problem is in this line

pm.rotate(rValue,0,0, obj, os=1)

obj should be the first argument, so it should be

pm.rotate(obj, (rValue,0,0), os=1)

but to make it even prettier you could use

obj.setRotation((rValue,0,0), os=1)

And also. Use pm.selected() instead of pm.ls(sl=1). It looks better

Another way to go about doing this..

from pymel.core import *
import random as rand

def rotateObjectsRandomly(axis, rotateRange):
    rotateValue = rand.random() * rotateRange
    for obj in objects:
        PyNode(str(selected()) + ".r" + axis).set(rotateValue)
    objectRotation = [[obj, obj.r.get()] for obj in selected()]
    print "\nObjects have been rotated in the {0} axis {1} degrees.\n".format(axis, rotateValue)
    return objectRotation

rotateObjectsRandomly("z", 360)

Since rand.random() returns a random value between 0 - 1, I just multiplied that by the rotateRange specified by the user..or in my preference I would just do away with that all together and just multiply it by 360...

You also don't need all the feedback I just think it looks nice when ran..

Objects have been rotated in the z axis 154.145898182 degrees.

# Result: [[nt.Transform(u'myCube'), dt.Vector([42.6541437517, 0.0, 154.145898182])]] # 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top