Reputation: 61
I was wondering if there is a way to create a progress window that shows how long until the moment your program finishes. This is what I have so far, but it's not doing what I expect.
I want it to run until all the curves have been created and then stop.
import maya.cmds as cmds
cmds.setAttr( "nParticle1Shape.lifespanMode", 2 )
cmds.setAttr( "nParticle1Shape.maxCount", 5 )
cmds.setAttr( "nParticle1Shape.lifespanRandom", 3 )
allParticleDictionary = {}
minFrames = cmds.playbackOptions( q=True, min=True )
maxFrames = cmds.playbackOptions( q=True, max=True )
running = 0
amount = 0
cmds.progressWindow( title='Doing Nothing',progress=amount,status='Sleeping: 0%',isInterruptable=True )
for currentFrame in range(0, int(maxFrames)):
cmds.currentTime( currentFrame, update=True, edit=True )
cmds.select( 'nParticle1' )
Particles = cmds.ls( sl=True, type='transform' )
for part in Particles:
for particleCount in range( 0,cmds.particle(part, q=True,ct=True) ):
particleName = cmds.particle( part, q=True, order=particleCount, at='id' )
particlesPosition = cmds.particle( part, q=True, order=particleCount, at='position' )
particleDictionary = {}
if str( particleName[0] ) in allParticleDictionary.keys():
particleDictionary = allParticleDictionary[str(particleName[0])]
particleDictionary[currentFrame] = particlesPosition
allParticleDictionary[str(particleName[0])] = particleDictionary
emptyFolder = cmds.group( em=True, n="Curves" )
for curveParticleId in allParticleDictionary.keys():
pointList = []
sortedKeyFrameList = sorted( allParticleDictionary[curveParticleId].keys() )
if len( sortedKeyFrameList ) > 1:
for keyFrame in sortedKeyFrameList:
pointList.append( allParticleDictionary[curveParticleId][keyFrame] )
curveObj = cmds.curve( name = "pCurve" + str(curveParticleId ), p = pointList)
Locators = cmds.spaceLocator( name = "locator" + str(curveParticleId) )
cmds.pathAnimation( Locators, stu=sortedKeyFrameList[0], etu=sortedKeyFrameList[-1], c=curveObj )
running = 1
# place all objects in Group called Curves
cmds.parent( curveObj, emptyFolder )
cmds.select( Locators )
cmds.delete()
while running == 0:
# Checks if the dialog has been cancelled
if cmds.progressWindow( query=True, isCancelled=True ) :
break
# Checks if end condition has been reached
if cmds.progressWindow( query=True, progress=True ) >= 100 :
break
amount += 20
cmds.progressWindow( edit=True, progress=amount, status=('Sleeping: ' + `amount` + '%' ) )
cmds.pause( seconds=1 )
cmds.progressWindow( endProgress=1 )
Upvotes: 2
Views: 3362
Reputation: 458
The preface is that I'm not entirely sure I got your logic right: as @theodox said, your indents seem wrong even after your latest correction.
Anyways, here's a version which should do you what you aim to, if I interpreted it right:
from maya import cmds
def checkProgressEscape():
# check if dialog has been cancelled
cancelled = cmds.progressWindow(query=True, isCancelled=True)
if cancelled:
cmds.progressWindow(endProgress=1)
return cancelled
def getAllParticlesDictionary(shape):
cmds.progressWindow(title='Fetch Particle Data', progress=0, status='Fetched: 0%', isInterruptable=True)
ptcsDict = {}
minFrames = int(cmds.playbackOptions( q=True, min=True))
maxFrames = int(cmds.playbackOptions( q=True, max=True))
nFrames = float(maxFrames - minFrames)
# better use the actual range, since you queried the playback options
for currentFrame in range(minFrames, maxFrames):
if checkProgressEscape():
return
amount = 100.0 / nFrames * (currentFrame - minFrames + 1)
cmds.progressWindow(edit=True, progress=amount, status='Fetched: %d%%' % amount)
# cmds.pause(seconds=.001)
cmds.currentTime(currentFrame, update=True, edit=True)
for particleCount in xrange(cmds.particle(shape, q=True, ct=True)):
particleId = int(cmds.particle(shape, q=True, order=particleCount, at='id')[0])
# better check the key exists first, then add your logic
if particleId not in ptcsDict.keys():
ptcsDict[particleId] = {}
ptcsDict[particleId][currentFrame] = cmds.particle(shape, q=True, order=particleCount, at='position')
cmds.progressWindow(endProgress=1)
return ptcsDict
def curvesFromParticle(ptcsDict):
cmds.progressWindow(title='Build Curves', progress=0, status='Building Curves: 0%', isInterruptable=True)
# this section had to be de-indented
emptyFolder = cmds.group(em=True, n="Curves")
ptcCount = len(ptcsDict)
for i, (curveParticleId, data) in enumerate(ptcsDict.iteritems()):
if checkProgressEscape():
return
sortedKeyFrameList = sorted(data.keys())
pointList = []
for keyFrame in sortedKeyFrameList:
pointList.append(ptcsDict[curveParticleId][keyFrame])
curveObj = cmds.curve(name="pCurve%d" % curveParticleId, p=pointList)
locators = cmds.spaceLocator( name = "locator%d" % curveParticleId)
cmds.pathAnimation( locators, stu=sortedKeyFrameList[0], etu=sortedKeyFrameList[-1], c=curveObj)
# place all objects in Group called Curves
cmds.parent(curveObj, emptyFolder)
cmds.delete(locators)
amount = 100 / ptcCount * float(i)
cmds.progressWindow(edit=True, progress=amount, status='Building Curves: %d%%' % amount)
cmds.progressWindow(endProgress=1)
ptcs = cmds.ls(typ='nParticle')
for shape in ptcs:
cmds.setAttr("%s.lifespanMode" % (shape, ), 2)
cmds.setAttr("%s.maxCount" % (shape, ), 100)
cmds.setAttr("%s.lifespanRandom" % (shape, ), 3)
ptcDict = getAllParticlesDictionary(shape)
if not ptcDict:
print 'data was not be fetched for %s; skipped' % (shape, )
continue
curvesFromParticle(ptcDict)
Above is a (slightly) modified version of your script; as you can see:
while
statements as they're not required by the progress bar: you're already looping in a for
statementendProgress
argument; you still need checking if the user escaped the process, thoughOn a side note, you might want to know (if you don't already) that maya is mostly single threaded. When using the API, you might work around some limitations but, generally, when using maya cmds you can be pretty sure you're working on a single thread.
This means the progress bar will be running on the same thread where your logic runs, hence limiting the performance of your script by several orders of magnitude: I've been doing some extensive work with particles + progress bars and I found that drawing the UI can be much slower than just running your logic. As the number of particles gets bigger, your script can become horribly slow, just because of your progress bar refreshing, not because of the logic itself.
A good practice is to update the progress only at known intervals (read: every n particles). Let's say you have 1000000 particles and you want to update the sidebar only by 5% steps, you would write something like this:
import random
cmds.progressWindow(title='Stepped Progress Bar', progress=0, status='Progress (stepped by 1): 0%%', isInterruptable=True)
limit = 1000000
step = 5
for i in xrange(limit):
progress = 100.0 / limit * i
if progress % step:
continue
cmds.progressWindow(e=1, progress=progress, status='Progress (stepped by 1): %d%%' % progress)
# the following is to simulate some processing time
cmds.pause(seconds=random.random() * 2)
cmds.progressWindow(endProgress=1)
Upvotes: 1