如何在Maya中通过Python创建进度窗口?

时间:2017-04-28 14:14:10

标签: python maya mel

我想知道是否有办法创建一个进度窗口,显示程序完成的时间。这是我到目前为止所做的,但它并没有达到我的预期。

我希望它一直运行,直到所有曲线都已创建然后停止。

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 )

1 个答案:

答案 0 :(得分:1)

前言是我不完全确定我的逻辑是正确的:as @theodox said, your indents seem wrong即使在你最近的修正之后也是如此。

无论如何,如果我解释正确的话,这里的版本应该是你的目标:

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)

以上是您的脚本的(略微)修改版本;如你所见:

  • 我将主要的逻辑块移动到函数中(只是为了可读性)
  • 我删除了while语句,因为进度条不需要它们:您已经在for语句中循环
  • 我还删除了您的进度检查,如果等于或大于100,因为一旦您退出循环,您可以认为您不再需要显示进度,只需调用侧边栏带endProgress参数的命令;尽管如此,你仍然需要检查用户是否转义了这个过程
  • 我添加了两个进度条"会话",一个用于循环获取粒子'数据和填充字典,一个用于构建曲线

在旁注中,您可能想知道(如果您还没有)maya is mostly single threaded。使用API​​时,您可能会遇到一些限制,但通常情况下,使用maya cmds 时,您可以非常确定自己是在单个线程上工作。

这意味着进度条将在您的逻辑运行的同一个线程上运行,因此将脚本的性能限制了几个数量级:我已经在使用粒子+进度条和I进行了大量工作发现绘制UI可能比运行逻辑慢得多。 随着粒子数量的增加,你的脚本变得非常慢,只是因为你的进度条刷新,不是因为逻辑本身。

一个好的做法是仅以已知的时间间隔更新进度(读取:每个 n 粒子)。假设您有100万个粒子,并且您只想以5%的步长更新侧边栏,您可以这样写:

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)